|
#!/usr/bin/python3 |
|
# |
|
# Source: https://gist.github.com/bysse/4959eae4f99a934dfc75a49eb7667d2b |
|
# |
|
import argparse |
|
import os.path |
|
import sys |
|
import time |
|
import urllib.request |
|
|
|
try: |
|
plot_available = True |
|
import matplotlib.pyplot as plt |
|
except: |
|
print('WARNING: Missing matplotlib, no plot available') |
|
plot_available = False |
|
|
|
URL_BASE = 'https://github.com/CSSEGISandData/COVID-19/raw/master/csse_covid_19_data/csse_covid_19_time_series/' |
|
CONFIRMED = 'time_series_covid19_confirmed_global.csv' |
|
DEATHS = 'time_series_covid19_deaths_global.csv' |
|
RECOVERED = 'time_series_covid19_recovered_global.csv' |
|
|
|
SEPARATOR = ' | ' |
|
|
|
|
|
def filedate(filename): |
|
if not os.path.exists(filename): |
|
return 0 |
|
stat = os.stat(filename) |
|
try: |
|
return stat.st_birthtime |
|
except AttributeError: |
|
return stat.st_mtime |
|
|
|
|
|
def verify_data_file(filename): |
|
if time.time() - filedate(filename) < 12 * 60 * 60: |
|
return |
|
if os.path.exists(filename): |
|
os.remove(filename) |
|
print("# Downloading", filename) |
|
urllib.request.urlretrieve(URL_BASE + filename, filename) |
|
|
|
|
|
parser = argparse.ArgumentParser(description='Compare covid-19 data between countries') |
|
parser.add_argument('countries', metavar='country', nargs='+', |
|
help='countries to display data for') |
|
parser.add_argument('-t', '--threshold', metavar='N', dest='threshold', type=int, default=1, |
|
help='the minimum number of cases to start comparison from') |
|
|
|
if plot_available: |
|
parser.add_argument('-p', '--plot', action='store_true', help='Create and show a plot') |
|
|
|
group = parser.add_mutually_exclusive_group(required = False) |
|
group.add_argument('--sick', action='store_true', help='Use the number of sick as the data set.') |
|
group.add_argument('--dead', action='store_true', help='Use the number of dead as the data set.') |
|
group.add_argument('--recovered', action='store_true', help='Use the number of recovered as the data set.') |
|
|
|
args = parser.parse_args() |
|
|
|
data_set = CONFIRMED |
|
plot_title = "Confirmed Cases" |
|
|
|
if args.dead: |
|
data_set = DEATHS |
|
plot_title = "Deaths" |
|
if args.recovered: |
|
data_set = RECOVERED |
|
plot_title = "Recoveries" |
|
|
|
verify_data_file(data_set) |
|
|
|
countries = [] |
|
for country in args.countries: |
|
countries.append(country.lower()) |
|
countries.sort() |
|
|
|
data = {} |
|
start = {} |
|
legend = None |
|
with open(data_set, 'r') as fp: |
|
for line in fp.readlines(): |
|
fields = line.split(',') |
|
|
|
if not legend: |
|
legend = list(map(lambda x: x.strip(), fields[4:])) |
|
legend = list(map(lambda x: x[:-3], legend)) |
|
continue |
|
|
|
country = fields[1].lower() |
|
if country in countries: |
|
cases = list(map(int, fields[4:])) |
|
data[country] = cases |
|
|
|
# find the first index |
|
start[country] = len(cases) |
|
for n in range(len(cases)): |
|
if cases[n] >= args.threshold: |
|
start[country] = n |
|
break |
|
|
|
# calculate column width |
|
columns = [1 + max(map(len, legend))] |
|
for country in countries: |
|
columns.append(len(country)) |
|
|
|
column_format = [] |
|
for col in columns: |
|
column_format.append( "%{}s".format(col) ) |
|
|
|
|
|
min_index = min(start.values()) |
|
|
|
def output(index, value, more_fields=True): |
|
print(column_format[index] % value, end='') |
|
|
|
if more_fields: |
|
print(SEPARATOR, end='') |
|
else: |
|
print() |
|
|
|
plot_data = {} |
|
|
|
num_columns = len(countries) |
|
for i in range(num_columns): |
|
output(0, 'date') |
|
output(1 + i, countries[i], i+1 != num_columns) |
|
plot_data[countries[i]] = [] |
|
|
|
for index in range(min_index, len(legend)): |
|
i = 0 |
|
for country in countries: |
|
offset = start[country] - min_index + index |
|
new_line = i+1 != num_columns |
|
|
|
if offset >= len(legend): |
|
output(0, '') |
|
output(1+i, '', new_line) |
|
plot_data[country].append(None) |
|
else: |
|
output(0, legend[offset]) |
|
output(1 + i, data[country][offset], new_line) |
|
plot_data[country].append(data[country][offset]) |
|
|
|
i += 1 |
|
|
|
if 'plot' in args and args.plot: |
|
for country, data in plot_data.items(): |
|
plt.plot(data, label=country) |
|
|
|
plt.title("COVID-19") |
|
plt.ylabel(plot_title) |
|
plt.xlabel("Days") |
|
plt.legend(loc="upper left") |
|
plt.grid() |
|
plt.show() |