<jupyter_start><jupyter_text>COVID-19 Growth Analysis * **Orignal_author:** <NAME> [URL](https://www.quantopian.com/posts/covid-19-growth-analysis)* **Adapted by:** <NAME> and <NAME>, University of Pretoria<jupyter_code>%pylab inline
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import pandas as pd
import seaborn as sns

import requests
import io

sns.set_context('talk')
plt.style.use('seaborn-whitegrid')
%matplotlib inline
number_of_days_since = 10 # You can change this to change the ouputs later
time_limit_since = [0,21] # days to up to after hitting number_of_days_since
def load_timeseries(name, 
                    base_url='https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series'):
    url = f'{base_url}/time_series_covid19_{name}_global.csv'
    print ("URL: ", url)
    csv = requests.get(url).text
    df = pd.read_csv(io.StringIO(csv), 
                     index_col=['Country/Region', 'Province/State', 'Lat', 'Long'])
    df['type'] = name.lower()
    df.columns.name = 'date'
    
    df = (df.set_index('type', append=True)
            .reset_index(['Lat', 'Long'], drop=True)
            .stack()
            .reset_index()
            .set_index('date')
         )
    df.index = pd.to_datetime(df.index)
    df.columns = ['country', 'state', 'type', 'cases']
    
    # Move HK to country level
    df.loc[df.state =='Hong Kong', 'country'] = 'Hong Kong'
    df.loc[df.state =='Hong Kong', 'state'] = np.nan
    
    # Aggregate large countries split by states
    df = pd.concat([df, 
                    (df.loc[~df.state.isna()]
                     .groupby(['country', 'date', 'type'])
                     .sum()
                     .rename(index=lambda x: x+' (total)', level=0)
                     .reset_index(level=['country', 'type']))
                   ])
    return df
df_confirmed = load_timeseries('confirmed')
df_confirmed.head()
df_confirmed.tail()
df_confirmed.describe()
# Estimated critical cases
p_crit = .05
df_confirmed = df_confirmed.assign(cases_crit=df_confirmed.cases*p_crit)

# Compute days relative to when 100 confirmed cases was crossed
df_confirmed.loc[:, 'days_since_' + str(number_of_days_since)] = np.nan
for country in df_confirmed.country.unique():
    df_confirmed.loc[(df_confirmed.country == country), 'days_since_'+ str(number_of_days_since)] = \
        np.arange(-len(df_confirmed.loc[(df_confirmed.country == country) & (df_confirmed.cases < number_of_days_since)]), 
                  len(df_confirmed.loc[(df_confirmed.country == country) & (df_confirmed.cases >= number_of_days_since)]))
## Plot Tooling
annotate_kwargs = dict(
    s='Based on COVID Data Repository by Johns Hopkins CSSE ({})\nAdapted by <NAME> and <NAME>, Original notebook by <NAME>'.format(df_confirmed.index.max().strftime('%B %d, %Y')), 
    xy=(0.05, 0.01), xycoords='figure fraction', fontsize=12)
figsize(16,9)
## Country names seem to change quite a bit
df_confirmed.country.unique()
european_countries = ['Italy','Spain']
large_engl_countries = ['US',]
asian_countries = ['Singapore','Korea, South']
south_american_countries = []

african_countries = ['Egypt' ]
south_africa = ['South Africa']

country_groups = [european_countries, asian_countries, large_engl_countries, south_africa, african_countries]
line_styles = ['-', ':', '--', '-.', '-']
def plot_countries(df, countries, min_cases=50, ls='-', col='cases'):
    for country in countries:
        df_country = df.loc[(df.country == country) & (df.cases >= min_cases)]
        if len(df_country) == 0:
            continue
        df_country.reset_index()[col].plot(label=country, ls=ls)
sns.set_palette(sns.hls_palette(8, l=.45, s=.8)) # 8 countries max
fig, ax = plt.subplots()

for countries, ls in zip(country_groups, line_styles):
    plot_countries(df_confirmed, countries, ls=ls)

x = np.linspace(0, plt.xlim()[1] - 1)
ax.plot(x, 100 * (1.33) ** x, ls='--', color='k', label='33% daily growth')

ax.set(yscale='log',
       title='Exponential growth of COVID-19 across countries',
       xlabel='Days from first '+str(number_of_days_since)+' confirmed cases',
       ylabel='Confirmed cases (log scale)')
ax.get_yaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
plt.legend(bbox_to_anchor=(.98, .5))
ax.annotate(**annotate_kwargs)
sns.despine();
plt.xlim(time_limit_since)
## Do you want to save this
# fig.savefig('../visualisation//covid-growth-countries.png', 
#                bbox_inches='tight', 
#                transparent=True,
#                pad_inches=0, dpi = 200)
#collapse-hide
fig, ax = plt.subplots()

for countries, ls in zip(country_groups, line_styles):
    plot_countries(df_confirmed, countries, ls=ls)

x = np.linspace(0, plt.xlim()[1] - 1)
ax.plot(x, 100 * (1.33) ** x, ls='--', color='k', label='33% daily growth')

ax.set(title='Exponential growth of COVID-19 across countries',
       xlabel='Days from first '+str(number_of_days_since)+' confirmed cases',
       ylabel='Confirmed cases', ylim=(0, 30000))
ax.legend(bbox_to_anchor=(1.0, 1.0))
ax.annotate(**annotate_kwargs)
sns.despine();
# plt.xlim([0,1000])
plt.ylim([0,1500])
plt.xlim(time_limit_since)
#collapse-hide
smooth_days = 4
fig, ax = plt.subplots(figsize=(14, 8))
df_confirmed['pct_change'] = (df_confirmed
                              .groupby('country')
                              .cases
                              .pct_change()
                              .rolling(smooth_days)
                              .mean()
)

for countries, ls in zip(country_groups, line_styles):
    (df_confirmed.set_index('country')
                 .loc[countries]
                 .loc[lambda x: x.cases > number_of_days_since]
                 .reset_index()
                 .set_index('days_since_'+str(number_of_days_since))
                 .groupby('country', sort=False)['pct_change']
                 .plot(ls=ls)
    )

ax.set(ylim=(0, 1),
       xlim=(0, 20),
       title='Are we seeing changes in daily growth rate?',
       xlabel='Days from first '+str(number_of_days_since)+' confirmed cases',
       ylabel='Daily percent change (smoothed over {} days)'.format(smooth_days),
)
ax.axhline(.33, ls='--', color='k')
ax.get_yaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
ax.legend(bbox_to_anchor=(1.0, 1.0))
sns.despine()
ax.annotate(**annotate_kwargs);<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15166172569823685, 'fraction_numerical': 0.01716336401934779, 'mean_word_length': 3.351663272233537, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 14, 'https://': 2, 'lorem ipsum': 0, 'www.': 1, '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': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '157982', 'license': 'MIT', 'n_tokens_mistral': 2299, 'n_tokens_neox': 2147, 'n_words': 435, 'path': 'notebooks/2020-03-28-international-growth-analysis.ipynb', 'repo_name': 'vaibhavijames/covid19za', 'size': '6453'}