From c682e13847a8a2b8f73c3f2aab868c290b151f74 Mon Sep 17 00:00:00 2001 From: fordprefect Date: Tue, 7 Jul 2020 13:04:39 +0200 Subject: [PATCH] various changes: fix lower axis value for all_countries, add population for each country from WikiData, fix data_getter for changed data format (added columns) --- all_countries.py | 41 +++++++- basics.py | 2 +- coronavis.py | 195 ++++++++++++++++++++++++++++++++++- death_per_case.py | 2 +- delay_from_china.py | 2 +- delay_from_usa.py | 2 +- doubling_time.py | 2 +- index.html | 5 +- normalized_to_first_death.py | 2 +- normalized_to_ten_cases.py | 2 +- percent_increase.py | 2 +- style.css | 2 +- 12 files changed, 238 insertions(+), 21 deletions(-) diff --git a/all_countries.py b/all_countries.py index 2e3f0f2..eda7ab5 100644 --- a/all_countries.py +++ b/all_countries.py @@ -2,30 +2,63 @@ Plot overview plot for each country separately """ import matplotlib.pyplot as pp +from mpl_toolkits.axisartist.parasite_axes import HostAxes, ParasiteAxes import numpy as np import time as time_module +import pickle basename="all_" -def plot(data, countries): +def plot(data, countries, pop): figsize = (10,5) + for loc in data: name = basename+loc time, new_cases, new_deaths, total_cases, total_deaths = data[loc] fig, ax1 = pp.subplots(num=name, figsize=figsize) + ax2 = ax1.twinx() + ax2.plot(time, np.array(total_deaths)*10, label="Total deaths (x10)", marker="", linestyle="--", color="green") + ax2.plot(time, total_cases, label=f"Total cases", marker="", linestyle="-", color="blue") + + ax1.plot(time, np.array(new_deaths)*10, label="raw new deaths (x10)", color="grey", linestyle=":") + ax1.plot(time[3:-3], np.convolve(new_deaths, np.ones((7,))/7, mode="valid")*10, label="new deaths 7day mean (x10)", color="black", linestyle="--", linewidth=2) + ax1.plot(time, new_cases, label="raw new cases", color="grey", linestyle="-") ax1.plot(time[3:-3], np.convolve(new_cases, np.ones((7,))/7, mode="valid"), label="new cases 7day mean", color="orange", linestyle="-", linewidth=2) - ax2 = ax1.twinx() - ax2.plot(time, total_cases, label=f"Total cases", marker="", linestyle="--", color="blue") + + # fix lower bound of plot + for ax in (ax1, ax2): + axis = ax.axis() + ax.axis([axis[0], axis[1], -1, axis[3]]) + + # disabled for now: put second total-cases-per-million-inhabitants axis besides total-cases-axis + if loc in pop and False: + # according to https://matplotlib.org/3.2.2/gallery/axisartist/demo_parasite_axes.html + host1 = HostAxes(ax1, [0.15, 0.1, 0.65, 0.8]) + par1 = ParasiteAxes(host1, sharex=host1) + host1.append(par1) + host2 = HostAxes(ax2, [0.15, 0.1, 0.65, 0.8]) + par2 = ParasiteAxes(host2, sharex=host1) + host2.append(par2) + + + + + ax3 = ax1.twinx() + ax3.plot(time, total_cases*1e6/pop[loc]['pop'], linestyle="", marker="") + ax3.set_ylabel("total cases per 1M inhabitants") #ax1.xticks(rotation=45) #ax1.set_xlabel("date") ax1.set_ylabel("new cases") ax2.set_ylabel("total cases") fig.legend(frameon=False, loc="upper left", bbox_to_anchor=(0,1), bbox_transform=ax1.transAxes) - pp.title(loc) + if loc in pop: + pp.title(f"{loc}, population = "+f"{pop[loc]['pop']:,}".replace(",",".")) + else: + pp.title(loc) fig.tight_layout() pp.text(0.002,0.005, f"plot generated {time_module.strftime('%Y-%m-%d %H:%M')}, CC-by-sa-nc, origin: dukun.de/corona, datasource: ourworldindata.org/coronavirus-source-data", color="dimgrey", fontsize=8, transform=fig.transFigure) diff --git a/basics.py b/basics.py index d94e6e4..4454bb0 100644 --- a/basics.py +++ b/basics.py @@ -4,7 +4,7 @@ Plot total cases of countries over time on log scale import matplotlib.pyplot as pp import numpy as np -def plot(data, countries): +def plot(data, countries, pop): figsize = (10,5) tcp, tc = pp.subplots(figsize=figsize) # total cases tdp, td = pp.subplots(figsize=figsize) # total deaths diff --git a/coronavis.py b/coronavis.py index cd94b95..40ace56 100644 --- a/coronavis.py +++ b/coronavis.py @@ -19,6 +19,187 @@ plots = ["basics", "death_per_case", "doubling_time", "all_countries", ] +### manual data +# population: sourced from wikidata and manually adjusted. not complete wrt the ECDC data! +pop = {'Afghanistan': {'wd_key': 'Afghanistan', 'pop': 34940837}, + 'Albania': {'wd_key': 'Albania', 'pop': 3020209}, + 'Algeria': {'wd_key': 'Algeria', 'pop': 41318142}, + 'Andorra': {'wd_key': 'Andorra', 'pop': 76177}, + 'Angola': {'wd_key': 'Angola', 'pop': 29784193}, + 'Antigua and Barbuda': {'wd_key': 'Antigua and Barbuda', 'pop': 102012}, + 'Argentina': {'wd_key': 'Argentina', 'pop': 44938712}, + 'Armenia': {'wd_key': 'Armenia', 'pop': 2930450}, + 'Australia': {'wd_key': 'Australia', 'pop': 24511800}, + 'Austria': {'wd_key': 'Austria', 'pop': 8809212}, + 'Azerbaijan': {'wd_key': 'Azerbaijan', 'pop': 10000000}, + 'Bahamas': {'wd_key': 'The Bahamas', 'pop': 395361}, + 'Bahrain': {'wd_key': 'Bahrain', 'pop': 1492584}, + 'Bangladesh': {'wd_key': 'Bangladesh', 'pop': 164669751}, + 'Barbados': {'wd_key': 'Barbados', 'pop': 285719}, + 'Belarus': {'wd_key': 'Belarus', 'pop': 9408400}, + 'Belgium': {'wd_key': 'Belgium', 'pop': 11431406}, + 'Belize': {'wd_key': 'Belize', 'pop': 374681}, + 'Benin': {'wd_key': 'Benin', 'pop': 11175692}, + 'Bhutan': {'wd_key': 'Bhutan', 'pop': 807610}, + 'Bolivia': {'wd_key': 'Bolivia', 'pop': 11051600}, + 'Bosnia and Herzegovina': {'wd_key': 'Bosnia and Herzegovina', 'pop': 3507017}, + 'Botswana': {'wd_key': 'Botswana', 'pop': 2291661}, + 'Brazil': {'wd_key': 'Brazil', 'pop': 210147125}, + 'Brunei': {'wd_key': 'Brunei', 'pop': 428697}, + 'Bulgaria': {'wd_key': 'Bulgaria', 'pop': 7000039}, + 'Burkina Faso': {'wd_key': 'Burkina Faso', 'pop': 19193382}, + 'Burundi': {'wd_key': 'Burundi', 'pop': 10864245}, + 'Cambodia': {'wd_key': 'Cambodia', 'pop': 16005373}, + 'Cameroon': {'wd_key': 'Cameroon', 'pop': 24053727}, + 'Canada': {'wd_key': 'Canada', 'pop': 37894799}, + 'Cape Verde': {'wd_key': 'Cape Verde', 'pop': 546388}, + 'Central African Republic': {'wd_key': 'Central African Republic', 'pop': 4659080}, + 'Chad': {'wd_key': 'Chad', 'pop': 15477751}, + 'Chile': {'wd_key': 'Chile', 'pop': 18054726}, + 'China': {'wd_key': "People's Republic of China", 'pop': 1409517397}, + 'Colombia': {'wd_key': 'Colombia', 'pop': 49065615}, + 'Comoros': {'wd_key': 'Comoros', 'pop': 823652}, + 'Costa Rica': {'wd_key': 'Costa Rica', 'pop': 4905769}, + 'Croatia': {'wd_key': 'Croatia', 'pop': 4105493}, + 'Cuba': {'wd_key': 'Cuba', 'pop': 11484636}, + 'Cyprus': {'wd_key': 'Cyprus', 'pop': 1141166}, + 'Czech Republic': {'wd_key': 'Czech Republic', 'pop': 10693939}, + 'Denmark': {'wd_key': 'Denmark', 'pop': 5827463}, + 'Djibouti': {'wd_key': 'Djibouti', 'pop': 956985}, + 'Dominica': {'wd_key': 'Dominica', 'pop': 73925}, + 'Dominican Republic': {'wd_key': 'Dominican Republic', 'pop': 10403761}, + 'Ecuador': {'wd_key': 'Ecuador', 'pop': 16624858}, + 'Egypt': {'wd_key': 'Egypt', 'pop': 94798827}, + 'El Salvador': {'wd_key': 'El Salvador', 'pop': 6420746}, + 'Equatorial Guinea': {'wd_key': 'Equatorial Guinea', 'pop': 1267689}, + 'Eritrea': {'wd_key': 'Eritrea', 'pop': 3497000}, + 'Estonia': {'wd_key': 'Estonia', 'pop': 1324820}, + 'Ethiopia': {'wd_key': 'Ethiopia', 'pop': 104957438}, + 'Fiji': {'wd_key': 'Fiji', 'pop': 905502}, + 'Finland': {'wd_key': 'Finland', 'pop': 5501043}, + 'France': {'wd_key': 'France', 'pop': 66628000}, + 'Gabon': {'wd_key': 'Gabon', 'pop': 2025137}, + 'Gambia': {'wd_key': 'The Gambia', 'pop': 2100568}, + 'Georgia': {'wd_key': 'Georgia', 'pop': 3717100}, + 'Germany': {'wd_key': 'Germany', 'pop': 83149300}, + 'Ghana': {'wd_key': 'Ghana', 'pop': 26908262}, + 'Greece': {'wd_key': 'Greece', 'pop': 10760421}, + 'Grenada': {'wd_key': 'Grenada', 'pop': 107825}, + 'Guatemala': {'wd_key': 'Guatemala', 'pop': 17263239}, + 'Guinea': {'wd_key': 'Equatorial Guinea', 'pop': 1267689}, + 'Guinea-Bissau': {'wd_key': 'Guinea-Bissau', 'pop': 1861283}, + 'Guyana': {'wd_key': 'Guyana', 'pop': 777859}, + 'Haiti': {'wd_key': 'Haiti', 'pop': 10981229}, + 'Honduras': {'wd_key': 'Honduras', 'pop': 9265067}, + 'Hungary': {'wd_key': 'Hungary', 'pop': 9937628}, + 'Iceland': {'wd_key': 'Iceland', 'pop': 357050}, + 'India': {'wd_key': 'India', 'pop': 1326093247}, + 'Indonesia': {'wd_key': 'Indonesia', 'pop': 263991379}, + 'Iran': {'wd_key': 'Iran', 'pop': 79966230}, + 'Iraq': {'wd_key': 'Iraq', 'pop': 38274618}, + 'Ireland': {'wd_key': 'Ireland', 'pop': 4761865}, + 'Israel': {'wd_key': 'Israel', 'pop': 9093000}, + 'Italy': {'wd_key': 'Italy', 'pop': 60317000}, + 'Jamaica': {'wd_key': 'Jamaica', 'pop': 2890299}, + 'Japan': {'wd_key': 'Japan', 'pop': 126785797}, + 'Jordan': {'wd_key': 'Jordan', 'pop': 10428241}, + 'Kazakhstan': {'wd_key': 'Kazakhstan', 'pop': 18276500}, + 'Kenya': {'wd_key': 'Kenya', 'pop': 48468138}, + 'Kuwait': {'wd_key': 'Kuwait', 'pop': 4600000}, + 'Kyrgyzstan': {'wd_key': 'Kyrgyzstan', 'pop': 6201500}, + 'Laos': {'wd_key': 'Laos', 'pop': 6858160}, + 'Latvia': {'wd_key': 'Latvia', 'pop': 1909000}, + 'Lebanon': {'wd_key': 'Lebanon', 'pop': 6100075}, + 'Lesotho': {'wd_key': 'Lesotho', 'pop': 2233339}, + 'Liberia': {'wd_key': 'Liberia', 'pop': 4731906}, + 'Libya': {'wd_key': 'Libya', 'pop': 6678567}, + 'Liechtenstein': {'wd_key': 'Liechtenstein', 'pop': 37922}, + 'Lithuania': {'wd_key': 'Lithuania', 'pop': 2790842}, + 'Luxembourg': {'wd_key': 'Luxembourg', 'pop': 626108}, + 'Macedonia': {'wd_key': 'North Macedonia', 'pop': 2075301}, + 'Madagascar': {'wd_key': 'Madagascar', 'pop': 25570895}, + 'Malawi': {'wd_key': 'Malawi', 'pop': 18622104}, + 'Malaysia': {'wd_key': 'Malaysia', 'pop': 31624264}, + 'Maldives': {'wd_key': 'Maldives', 'pop': 436330}, + 'Mali': {'wd_key': 'Mali', 'pop': 18541980}, + 'Malta': {'wd_key': 'Malta', 'pop': 465292}, + 'Mauritania': {'wd_key': 'Mauritania', 'pop': 4420184}, + 'Mauritius': {'wd_key': 'Mauritius', 'pop': 1264613}, + 'Mexico': {'wd_key': 'Mexico', 'pop': 130526945}, + 'Moldova': {'wd_key': 'Moldova', 'pop': 2550900}, + 'Monaco': {'wd_key': 'Monaco', 'pop': 38695}, + 'Mongolia': {'wd_key': 'Mongolia', 'pop': 3075647}, + 'Montenegro': {'wd_key': 'Montenegro', 'pop': 622359}, + 'Morocco': {'wd_key': 'Morocco', 'pop': 36029138}, + 'Mozambique': {'wd_key': 'Mozambique', 'pop': 29668834}, + 'Myanmar': {'wd_key': 'Myanmar', 'pop': 53370609}, + 'Namibia': {'wd_key': 'Namibia', 'pop': 2533794}, + 'Nepal': {'wd_key': 'Nepal', 'pop': 29400000}, + 'Netherlands': {'wd_key': 'Kingdom of the Netherlands', 'pop': 17100715}, + 'New Zealand': {'wd_key': 'New Zealand', 'pop': 4942500}, + 'Nicaragua': {'wd_key': 'Nicaragua', 'pop': 6217581}, + 'Niger': {'wd_key': 'Niger', 'pop': 21477348}, + 'Nigeria': {'wd_key': 'Nigeria', 'pop': 190886311}, + 'Norway': {'wd_key': 'Norway', 'pop': 5367580}, + 'Oman': {'wd_key': 'Oman', 'pop': 4829480}, + 'Pakistan': {'wd_key': 'Pakistan', 'pop': 197015955}, + 'Panama': {'wd_key': 'Panama', 'pop': 4098587}, + 'Papua New Guinea': {'wd_key': 'Papua New Guinea', 'pop': 8251162}, + 'Paraguay': {'wd_key': 'Paraguay', 'pop': 6811297}, + 'Peru': {'wd_key': 'Peru', 'pop': 29381884}, + 'Philippines': {'wd_key': 'Philippines', 'pop': 104918090}, + 'Poland': {'wd_key': 'Poland', 'pop': 38433600}, + 'Portugal': {'wd_key': 'Portugal', 'pop': 10600000}, + 'Qatar': {'wd_key': 'Qatar', 'pop': 2639211}, + 'Romania': {'wd_key': 'Romania', 'pop': 19586539}, + 'Russia': {'wd_key': 'Russia', 'pop': 146804372}, + 'Rwanda': {'wd_key': 'Rwanda', 'pop': 12208407}, + 'Saint Kitts and Nevis': {'wd_key': 'Saint Kitts and Nevis', 'pop': 55345}, + 'Saint Lucia': {'wd_key': 'Saint Lucia', 'pop': 178844}, + 'Saint Vincent and the Grenadines': {'wd_key': 'Saint Vincent and the Grenadines', 'pop': 109897}, + 'San Marino': {'wd_key': 'San Marino', 'pop': 33400}, + 'Saudi Arabia': {'wd_key': 'Saudi Arabia', 'pop': 33000000}, + 'Senegal': {'wd_key': 'Senegal', 'pop': 15850567}, + 'Serbia': {'wd_key': 'Serbia', 'pop': 7022268}, + 'Seychelles': {'wd_key': 'Seychelles', 'pop': 95843}, + 'Sierra Leone': {'wd_key': 'Sierra Leone', 'pop': 7557212}, + 'Singapore': {'wd_key': 'Singapore', 'pop': 5888926}, + 'Slovakia': {'wd_key': 'Slovakia', 'pop': 5397036}, + 'Slovenia': {'wd_key': 'Slovenia', 'pop': 2066880}, + 'Somalia': {'wd_key': 'Somalia', 'pop': 11031386}, + 'South Africa': {'wd_key': 'South Africa', 'pop': 57725600}, + 'South Korea': {'wd_key': 'South Korea', 'pop': 51466201}, + 'South Sudan': {'wd_key': 'South Sudan', 'pop': 12575714}, + 'Spain': {'wd_key': 'Spain', 'pop': 46733038}, + 'Sri Lanka': {'wd_key': 'Sri Lanka', 'pop': 21444000}, + 'Sudan': {'wd_key': 'Sudan', 'pop': 40533330}, + 'Suriname': {'wd_key': 'Suriname', 'pop': 563402}, + 'Sweden': {'wd_key': 'Sweden', 'pop': 10343403}, + 'Switzerland': {'wd_key': 'Switzerland', 'pop': 8466017}, + 'Syria': {'wd_key': 'Syria', 'pop': 18269868}, + 'Tajikistan': {'wd_key': 'Tajikistan', 'pop': 8921343}, + 'Tanzania': {'wd_key': 'Tanzania', 'pop': 57310019}, + 'Thailand': {'wd_key': 'Thailand', 'pop': 65931550}, + 'Timor': {'wd_key': 'East Timor', 'pop': 1296311}, + 'Togo': {'wd_key': 'Togo', 'pop': 7797694}, + 'Trinidad and Tobago': {'wd_key': 'Trinidad and Tobago', 'pop': 1369125}, + 'Tunisia': {'wd_key': 'Tunisia', 'pop': 11565204}, + 'Turkey': {'wd_key': 'Turkey', 'pop': 82003882}, + 'Uganda': {'wd_key': 'Uganda', 'pop': 42862958}, + 'Ukraine': {'wd_key': 'Ukraine', 'pop': 42558328}, + 'United Arab Emirates': {'wd_key': 'United Arab Emirates', 'pop': 9400145}, + 'United Kingdom': {'wd_key': 'United Kingdom', 'pop': 66022273}, + 'United States': {'wd_key': 'United States of America', 'pop': 325145963}, + 'Uruguay': {'wd_key': 'Uruguay', 'pop': 3456750}, + 'Uzbekistan': {'wd_key': 'Uzbekistan', 'pop': 32387200}, + 'Vatican': {'wd_key': 'Vatican City', 'pop': 1000}, + 'Venezuela': {'wd_key': 'Venezuela', 'pop': 28515829}, + 'Vietnam': {'wd_key': 'Vietnam', 'pop': 94660000}, + 'Yemen': {'wd_key': 'Yemen', 'pop': 28250420}, + 'Zambia': {'wd_key': 'Zambia', 'pop': 17094130}, + 'Zimbabwe': {'wd_key': 'Zimbabwe', 'pop': 16529904} +} + ### def get_data(): """fetch data from remote, cache locally and reorganize internal data @@ -41,7 +222,14 @@ def get_data(): with open(datafile, "r") as f: reader = csv.reader(f) for row in reader: - date,location,new_cases,new_deaths,total_cases,total_deaths = row + if len(row) == 6: + date,location,new_cases,new_deaths,total_cases,total_deaths = row + elif len(row) == 10: + date,location,new_cases,new_deaths,total_cases,total_deaths,weekly_cases,weekly_deaths,biweekly_cases,biweekly_deaths = row + else: + print(f"WARNING! Table format changed, new header:\n{row})") + exit(1) + if location=="location": # table header continue @@ -72,8 +260,5 @@ def get_data(): data = get_data() for plot in plots: - #try: i = importlib.import_module(plot) - i.plot(data, countries) - #except: - # print(f"plotting {plot} failed") + i.plot(data, countries, pop) diff --git a/death_per_case.py b/death_per_case.py index 162254d..fe56dc1 100644 --- a/death_per_case.py +++ b/death_per_case.py @@ -5,7 +5,7 @@ import matplotlib.pyplot as pp import numpy as np name="death_per_case" -def plot(data, countries): +def plot(data, countries, pop): figsize = (10,5) for loc in data: if loc not in countries: diff --git a/delay_from_china.py b/delay_from_china.py index cc67879..6259949 100644 --- a/delay_from_china.py +++ b/delay_from_china.py @@ -5,7 +5,7 @@ import matplotlib.pyplot as pp import numpy as np name="delay" -def plot(data, countries): +def plot(data, countries, pop): figsize = (10,5) # plot delay diff --git a/delay_from_usa.py b/delay_from_usa.py index 7aca57f..3087ed9 100644 --- a/delay_from_usa.py +++ b/delay_from_usa.py @@ -5,7 +5,7 @@ import matplotlib.pyplot as pp import numpy as np name="delay" -def plot(data, countries): +def plot(data, countries, pop): figsize = (10,5) for loc in data: if loc not in countries: diff --git a/doubling_time.py b/doubling_time.py index 3478446..ce4c6d3 100644 --- a/doubling_time.py +++ b/doubling_time.py @@ -8,7 +8,7 @@ name="doubling_time" def moving_average(x, w): return np.convolve(x, np.ones(w), 'valid') / w -def plot(data, countries): +def plot(data, countries, pop): figsize = (10,5) for loc in data: if loc not in countries: diff --git a/index.html b/index.html index 11f3800..00473a9 100644 --- a/index.html +++ b/index.html @@ -5,11 +5,10 @@ - +
-

Visualisierung zu Corona2020

+

Visualisierung zu CoViD19

-
==> Sehr gute automatisiert aktualisierte Plot für Deutschland <==

diff --git a/normalized_to_first_death.py b/normalized_to_first_death.py index 00b6c3c..e8cd2b5 100644 --- a/normalized_to_first_death.py +++ b/normalized_to_first_death.py @@ -5,7 +5,7 @@ import matplotlib.pyplot as pp import numpy as np name="normalized_to_first_death" -def plot(data, countries): +def plot(data, countries, pop): figsize = (10,5) for loc in data: if loc not in countries: diff --git a/normalized_to_ten_cases.py b/normalized_to_ten_cases.py index 313b267..9c1124b 100644 --- a/normalized_to_ten_cases.py +++ b/normalized_to_ten_cases.py @@ -5,7 +5,7 @@ import matplotlib.pyplot as pp import numpy as np name="normalized_to_100_cases" -def plot(data, countries): +def plot(data, countries, pop): figsize = (10,5) for loc in data: if loc not in countries: diff --git a/percent_increase.py b/percent_increase.py index c416644..79418c4 100644 --- a/percent_increase.py +++ b/percent_increase.py @@ -8,7 +8,7 @@ name="percent_increase" def moving_average(x, w): return np.convolve(x, np.ones(w), 'valid') / w -def plot(data, countries): +def plot(data, countries, pop): figsize = (10,5) for loc in data: if loc not in countries: diff --git a/style.css b/style.css index e4da8c8..7b614b9 100644 --- a/style.css +++ b/style.css @@ -2,7 +2,7 @@ div.box { color:#cecece; background-image: url('/linen_login.jpg'); background-size: 100%; - width: 90%; + width: 100%; height: 90%; margin: 0px auto; overflow: auto;