Skip to content

Instantly share code, notes, and snippets.

@andyljones
Created February 13, 2021 15:36
Show Gist options
  • Save andyljones/84cb250faf312f99a88c543c0104e9e7 to your computer and use it in GitHub Desktop.
Save andyljones/84cb250faf312f99a88c543c0104e9e7 to your computer and use it in GitHub Desktop.
A naive estimate in the reduction in IFR you get from vaccinating the most vulnerable fraction of the population
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from io import StringIO
import matplotlib.ticker as mtick
# Source: p11, https://www.imperial.ac.uk/media/imperial-college/medicine/mrc-gida/2020-10-29-COVID19-Report-34.pdf
IFR = """
0-4 0.00 (0.00, 0.03) 0.00 (0.00, 0.03)
5-9 0.01 (0.00, 0.06) 0.01 (0.00, 0.06)
10-14 0.01 (0.00, 0.11) 0.01 (0.00, 0.10)
15-19 0.02 (0.00, 0.18) 0.02 (0.00, 0.17)
20-24 0.03 (0.00, 0.3) 0.02 (0.00, 0.28)
25-29 0.04 (0.00, 0.46) 0.04 (0.00, 0.44)
30-34 0.06 (0.01, 0.71) 0.06 (0.01, 0.67)
35-39 0.10 (0.01, 1.03) 0.09 (0.01, 0.98)
40-44 0.16 (0.02, 1.47) 0.15 (0.02, 1.37)
45-49 0.24 (0.03, 2.03) 0.23 (0.03, 1.88)
50-54 0.38 (0.05, 2.74) 0.36 (0.05, 2.52)
55-59 0.60 (0.10, 3.64) 0.57 (0.10, 3.32)
60-64 0.94 (0.18, 4.79) 0.89 (0.18, 4.34)
65-69 1.47 (0.35, 6.27) 1.39 (0.34, 5.64)
70-74 2.31 (0.65, 8.21) 2.17 (0.64, 7.35)
75-79 3.61 (1.21, 10.81) 3.39 (1.19, 9.65)
80-84 5.66 (2.23, 14.37) 5.3 (2.19, 12.81)
85-89 8.86 (4.06, 19.36) 8.28 (3.98, 17.25)
90+ 17.37 (9.7, 31.12) 16.19 (9.44, 27.78)"""
# Source: https://www.ons.gov.uk/peoplepopulationandcommunity/populationandmigration/populationprojections/datasets/tablea21principalprojectionukpopulationinagegroups
AGE = """
0-4 3,914 3,854 3,801
5-9 4,139 4,153 4,153
10-14 3,859 3,956 4,049
15-19 3,669 3,653 3,676
20-24 4,185 4,155 4,118
25-29 4,527 4,525 4,490
30-34 4,463 4,505 4,535
35-39 4,372 4,402 4,418
40-44 3,993 4,021 4,099
45-49 4,507 4,405 4,312
50-54 4,674 4,662 4,618
55-59 4,294 4,408 4,514
60-64 3,673 3,758 3,862
65-69 3,396 3,371 3,363
70-74 3,252 3,320 3,369
75-79 2,236 2,327 2,412
80-84 1,673 1,716 1,738
85-89 1,024 1,041 1,058
90-94 448 459 469
95-99 123 128 128
100 & over 13 13 15"""
VACCINATED = .2
def load_ifr():
return (pd.read_csv(StringIO(IFR), sep=' ', header=None)
.rename(columns={0: 'age', 1: 'ifr'})
.set_index('age')['ifr']
.div(100)
.pipe(pd.to_numeric))
def load_age():
age = (pd.read_csv(StringIO(AGE), sep='\t', header=None)
.rename(columns={0: 'age', 3: 'pop'})
.set_index('age')['pop']
.str.replace(',', '').pipe(pd.to_numeric)
.rename(index=lambda s: s.strip()))
age['90+'] = age['90-94'] + age['95-99'] + age['100 & over']
age = age.drop(['90-94', '95-99', '100 & over'])
return age/age.sum()
def vaccinated_ifrs(age, ifr):
rates = {}
cumulants = age[::-1].cumsum()
for v in [0.] + cumulants.values.tolist():
rates[v] = (cumulants > v).mul(ifr).mul(age).sum()
return pd.Series(rates)
def plot(rates):
with plt.style.context('seaborn-poster'):
ax = rates.mul(100).rename(lambda i: 100*i).plot()
ax.set_ylim(0, 100*rates.max())
ax.set_xlim(0, 100)
ax.axvspan(0, 20, color='k', alpha=.2)
ax.grid(True)
ax.yaxis.set_major_formatter(mtick.PercentFormatter())
ax.xaxis.set_major_formatter(mtick.PercentFormatter())
ax.set_ylabel('population ifr')
ax.set_xlabel('fraction of population vaccinated, starting with eldest')
ax.set_title('a naive estimate of IFR based on UK vaccination strategy;\n20% vaccinated means ~80% reduction in IFR')
if __name__ == '__main__':
ifr = load_ifr()
age = load_age()
rates = vaccinated_ifrs(age, ifr)
plot(rates)
@andyljones
Copy link
Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment