Created
February 13, 2021 15:36
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
Author
andyljones
commented
Feb 13, 2021
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment