<jupyter_start><jupyter_text>Graphing: time vs. casesThis tutorial goes over how to use Seaborn to plot data accessed through our package. We will create a plot with "days since first case" on the x axis, and "number of confirmed cases" on the y axis, with different curves for different countries. We will include the countries with the 10 highest current infection counts.<jupyter_code>import covid19pandas as cod

import seaborn as sns
import matplotlib.pyplot as plt

import pandas as pd
import numpy as np
import datetime<jupyter_output><empty_output><jupyter_text>First, we will find which 10 countries have the highest current infection counts.<jupyter_code>data_type = "cases" # By using a variable, we can easily switch to plot a different data type
data = cod.get_data_jhu(data_type=data_type)

last_day = data["date"].max() # Get the last recorded day

current_ct = data[data['date'] == last_day] # Pull all records for that day
current_ct = current_ct[["Country/Region", data_type]] # Drop unnecessary columns
current_ct = current_ct.groupby("Country/Region").aggregate(np.sum)

top_ten_names = current_ct.sort_values(by=data_type).tail(10)
top_ten_names<jupyter_output>These data were obtained from Johns Hopkins University (https://github.com/CSSEGISandData/COVID-19).<jupyter_text>Now, we will select daily data for just those countries, and sum up counts for sub-regions within those countries.<jupyter_code>top_ten_cts = data[data["Country/Region"].isin(top_ten_names.index)] # Filter out other countries
top_ten_cts = top_ten_cts[["date", "Country/Region", data_type]] # Get the columns we want
top_ten_cts = top_ten_cts.groupby(
    ["date", "Country/Region"]).aggregate(np.sum).reset_index() # Sum up total cases per day, per country

top_ten_cts.head(10)<jupyter_output><empty_output><jupyter_text>Now we need to replace the dates with the number of days since the 100th case in that country.<jupyter_code>country_groups = top_ten_cts.groupby("Country/Region") # Create pandas GroupBy object on country

country_day_cts = pd.DataFrame(columns=["day", "Country/Region", data_type]) # We'll append everything to this
for country in top_ten_names.index:
    
    country_tbl = country_groups.get_group(country)
    country_tbl = country_tbl[country_tbl[data_type] >= 100] # Select only days with 100 or more cases
    assert(country_tbl["date"].duplicated().sum() == 0) # Verify there are no duplicate days
    
    day_number_col = range(0, len(country_tbl.index)) # Generate a column of day number since 100 cases
    country_tbl.insert(loc=0, column="day", value=day_number_col) # Insert the column
    country_tbl = country_tbl.drop(columns="date") # We don't need the date column anymore
    
    country_day_cts = pd.concat([country_day_cts, country_tbl]).sort_values(by="day")

country_day_cts = country_day_cts.apply(pd.to_numeric, errors="ignore")

country_day_cts.head(5)
country_day_cts.tail(5)<jupyter_output><empty_output><jupyter_text>We can now plot our data.<jupyter_code>sns.set_style("darkgrid") # Set the plot colors
plt.figure(figsize=(15, 8)) # Set desired dimensions

ax = sns.lineplot(x="day", 
            y=data_type, 
            data=country_day_cts,
            hue="Country/Region")

ax.set(title="Days since 100th case vs. number of cases, log scale",
      xlabel="Days since 100th case",
      ylabel="Number of cases (log scale)",
      yscale="log")

plt.show()<jupyter_output><empty_output><jupyter_text>We'll finish by creating a function that does all of that at once, and then plugging in different parameters.<jupyter_code>def plot_days_vs_count(data_type="cases", min_count=100, num_countries=10, y_logscale=True):
    
    data = cod.get_data_jhu(data_type=data_type) # Get the data
    last_day = data["date"].max() # Get the last recorded day

    current_ct = data[data['date'] == last_day] # Pull all records for that day
    current_ct = current_ct[["Country/Region", data_type]] # Drop unnecessary columns
    current_ct = current_ct.groupby("Country/Region").aggregate(np.sum)

    top_names = current_ct.sort_values(by=data_type).tail(num_countries)
    top_cts = data[data["Country/Region"].isin(top_names.index)] # Filter out other countries
    top_cts = top_cts[["date", "Country/Region", data_type]] # Get the columns we want
    top_cts = top_cts.groupby(
        ["date", "Country/Region"]).aggregate(np.sum).reset_index() # Sum up total cases per day, per country

    country_groups = top_cts.groupby("Country/Region") # Create pandas GroupBy object on country

    country_day_cts = pd.DataFrame(columns=["day", "Country/Region", data_type]) # We'll append everything to this
    for country in top_names.index:

        country_tbl = country_groups.get_group(country)
        country_tbl = country_tbl[country_tbl[data_type] >= min_count] # Select only days with 100 or more cases
        assert(country_tbl["date"].duplicated().sum() == 0) # Verify there are no duplicate days

        day_number_col = range(0, len(country_tbl.index)) # Generate a column of day number since 100 cases
        country_tbl.insert(loc=0, column="day", value=day_number_col) # Insert the column
        country_tbl = country_tbl.drop(columns="date") # We don't need the date column anymore

        country_day_cts = pd.concat([country_day_cts, country_tbl]).sort_values(by="day")

    country_day_cts = country_day_cts.apply(pd.to_numeric, errors="ignore")
    country_day_cts

    sns.set_style("darkgrid") # Set the plot colors
    plt.figure(figsize=(15, 8)) # Set desired dimensions

    ax = sns.lineplot(x="day", 
                y=data_type, 
                data=country_day_cts,
                hue="Country/Region")

    if y_logscale:
        ax.set(title=f"Days since 100th case vs. number of {data_type}, log scale",
              xlabel="Days since 100th case",
              ylabel=f"Number of {data_type} (log scale)",
              yscale="log")
    else:
        ax.set(title=f"Days since 100th case vs. number of {data_type}, no log scale",
              xlabel="Days since 100th case",
              ylabel=f"Number of {data_type}")
        
    plt.show()<jupyter_output><empty_output><jupyter_text>The graph looks pretty interesting if we don't have the y axis on a log scale:<jupyter_code>plot_days_vs_count(data_type="cases", min_count=100, num_countries=10, y_logscale=False)<jupyter_output>These data were obtained from Johns Hopkins University (https://github.com/CSSEGISandData/COVID-19).<jupyter_text>Here are plots for deaths and recovered counts.<jupyter_code>plot_days_vs_count(data_type="deaths", min_count=100, num_countries=10, y_logscale=True)
plot_days_vs_count(data_type="recovered", min_count=100, num_countries=10, y_logscale=True)<jupyter_output>These data were obtained from Johns Hopkins University (https://github.com/CSSEGISandData/COVID-19).
{'fraction_non_alphanumeric': 0.10484813084112149, 'fraction_numerical': 0.01255841121495327, 'mean_word_length': 4.7218045112781954, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 32, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '36493', 'license': 'Apache-2.0', 'n_tokens_mistral': 2269, 'n_tokens_neox': 2151, 'n_words': 584, 'path': 'docs/tutorial2_graph_time_vs_cases.ipynb', 'repo_name': 'mwang87/covid19pandas', 'size': '6848'}