Skip to content

Instantly share code, notes, and snippets.

@bysse
Last active April 2, 2020 08:16
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bysse/4959eae4f99a934dfc75a49eb7667d2b to your computer and use it in GitHub Desktop.
Save bysse/4959eae4f99a934dfc75a49eb7667d2b to your computer and use it in GitHub Desktop.
Utility for comparing COVID-19 cases side by side between countries.
#!/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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment