General updates
[covid19.git] / covid.md
index 318cd5d6f044f989c7d1073176c6bb869653adf6..b06cd354a8c39f61c6211a29f188af2d2b82dc1f 100644 (file)
--- a/covid.md
+++ b/covid.md
@@ -18,9 +18,11 @@ Data from [European Centre for Disease Prevention and Control](https://www.ecdc.
 ```python
 import itertools
 import collections
+import json
 import pandas as pd
 import numpy as np
 from scipy.stats import gmean
+import datetime
 
 import matplotlib as mpl
 import matplotlib.pyplot as plt
@@ -300,7 +302,10 @@ plt.savefig('covid_deaths_total_log.png')
 ```
 
 ```python
-deaths_pc.plot(figsize=(10, 6), title="Deaths per capita, linear")
+ax = deaths_pc.plot(figsize=(10, 6), title="Deaths per capita, linear")
+for c in deaths_pc.columns:
+    lvi = deaths_pc[c].last_valid_index()
+    ax.text(x = lvi + 1, y = deaths_pc[c][lvi], s = c)
 plt.savefig('covid_deaths_per_capita_linear.png')
 ```
 
@@ -505,20 +510,24 @@ data_since_threshold.replace([np.inf, -np.inf], np.nan).groupby(level=1).last().
 
 ```python
 it_since_threshold = data_since_threshold.replace([np.inf, -np.inf], np.nan).loc[(slice(None), ['IT']), :]
-it_since_threshold.index.max()[0]
+s_end = it_since_threshold.index.max()[0]
+s_end
 ```
 
 ```python
 uk_projection = data_since_threshold.replace([np.inf, -np.inf], np.nan).loc[(slice(None), ['UK']), :]
-uk_projection.index.max()[0]
+s_start = uk_projection.index.max()[0] + 1
+s_start
 ```
 
 ```python
-proj = it_since_threshold.loc[(slice(60, 77), slice(None)), ['cases', 'deaths']]
+proj = it_since_threshold.loc[(slice(s_start, s_end), slice(None)), ['cases', 'deaths']]
 proj.index = pd.MultiIndex.from_tuples([(n, 'UK') for n, _ in proj.index], names=proj.index.names)
 proj
 ```
 
+Projected deaths, UK following IT trend from now.
+
 ```python
 uk_projection = uk_projection.append(proj, sort=True)
 uk_projection.deaths.sum()
@@ -528,6 +537,185 @@ uk_projection.deaths.sum()
 it_since_threshold.deaths.sum()
 ```
 
+```python
+with open('excess_deaths.json') as f:
+    excess_deaths_data = json.load(f)
+excess_deaths_data
+```
+
+```python
+excess_deaths_upto = '2020-05-08'
+excess_deaths = 54500
+```
+
+```python
+excess_deaths_upto = excess_deaths_data['end_date']
+excess_deaths = excess_deaths_data['excess_deaths']
+```
+
+Recorded deaths in period where ONS has reported total deaths
+
+```python
+reported_deaths = base_data.loc['UK'][:excess_deaths_upto]['deaths'].sum()
+reported_deaths
+```
+
+```python
+excess_deaths / reported_deaths
+```
+
+True deaths to date, if we follow the scaling of excess deaths over reported deaths so far.
+
+```python
+uk_covid_deaths = data_since_threshold.replace([np.inf, -np.inf], np.nan).loc[(slice(None), ['UK']), 'deaths_culm'].iloc[-1]
+uk_covid_deaths
+```
+
+```python
+data_since_threshold.replace([np.inf, -np.inf], np.nan).loc[(slice(None), ['IT']), 'dateRep'].iloc[-1] + pd.Timedelta(s_end - s_start, unit='days')
+```
+
+```python
+data_since_threshold.replace([np.inf, -np.inf], np.nan).loc[(slice(None), ['UK']), 'dateRep'].iloc[-1].strftime("%Y-%m-%d")
+```
+
+```python
+uk_covid_deaths * excess_deaths / reported_deaths
+```
+
+```python
+uk_projection.deaths.sum() * excess_deaths / reported_deaths
+```
+
+# Write results to summary file
+
+```python
+with open('covid_summary.md', 'w') as f:
+    f.write('% Covid death data summary\n')
+    f.write('% Neil Smith\n')
+    f.write(f'% Created on {datetime.datetime.now().strftime("%Y-%m-%d")}\n')
+    f.write('\n')
+        
+    last_uk_date = data_since_threshold.replace([np.inf, -np.inf], np.nan).loc[(slice(None), ['UK']), 'dateRep'].iloc[-1]
+    f.write(f'> Last UK data from {last_uk_date.strftime("%Y-%m-%d")}\n')
+```
+
+```python
+with open('covid_summary.md', 'a') as f:
+    f.write('\n')
+    f.write('## Headlines\n')
+    f.write('\n')
+    f.write('| []() | |\n')
+    f.write('|:---|---:|\n')
+    f.write(f'| Deaths reported so far | {reported_deaths} | \n')
+    f.write(f'| Total Covid deaths to date | {uk_covid_deaths * excess_deaths / reported_deaths:.0f} |\n')
+    projection_date = data_since_threshold.replace([np.inf, -np.inf], np.nan).loc[(slice(None), ['IT']), 'dateRep'].iloc[-1] + pd.Timedelta(s_end - s_start, unit='days')
+    f.write(f'| Projected total deaths up to {projection_date.strftime("%Y-%m-%d")} | {uk_projection.deaths.sum() * excess_deaths / reported_deaths:.0f} | \n')
+    f.write('\n')
+```
+
+```python
+with open('covid_summary.md', 'a') as f:
+    f.write('\n')
+    f.write('## Total deaths\n')
+    f.write(f'Time based on days since {DEATH_COUNT_THRESHOLD} deaths\n')
+    f.write('\n')
+    f.write('![Total deaths](covid_deaths_total_linear.png)\n')
+    f.write('\n')
+    f.write('| Country ID | Country name | Total deaths |\n')
+    f.write('|:-----------|:-------------|-------------:|\n')
+    for c in sorted(COUNTRIES_CORE):
+        lvi = deaths[c].last_valid_index()
+        f.write(f'| {c} | {countries.loc[c].countriesAndTerritories} | {int(deaths[c][lvi])} |\n')
+    f.write('\n')
+```
+
+```python
+with open('covid_summary.md', 'a') as f:
+    f.write('\n')
+    f.write('## All-causes deaths, UK\n')
+    f.write('\n')
+    f.write('![All-causes deaths](deaths-radar.png)\n')
+    f.write('\n')
+    f.write('### Excess deaths\n')
+    f.write('\n')
+    f.write(f'From week ending 20 March 2020, there have been approximately **{excess_deaths:.0f}** excess deaths, over the average for the previous five years.\n')
+    f.write('\n')
+```
+
+```python
+with open('covid_summary.md', 'a') as f:
+    f.write(f'In that period, the UK reported {reported_deaths} Covid deaths.\n')
+    f.write(f'That means the actual number of Covid death is about {excess_deaths / reported_deaths:.2f} times higher than the reported figures.\n')
+    f.write('\n')
+    f.write(f'The UK has reported {uk_covid_deaths} deaths so far.\n')
+    f.write(f'Using the scaling factor above, I infer that there have been **{uk_covid_deaths * excess_deaths / reported_deaths:.0f}** total deaths so far.\n')
+    f.write('\n')
+```
+
+```python
+with open('covid_summary.md', 'a') as f:
+    f.write('\n')
+    f.write('## Deaths per day\n')
+    f.write(f'Based on a 7-day moving average\n')
+    f.write('\n')
+    f.write('![Deaths per day](covid_deaths_per_day_7.png)\n')
+    f.write('\n')
+```
+
+```python
+with open('covid_summary.md', 'a') as f:
+    f.write('\n')
+    f.write('## Projected deaths\n')
+    f.write(f"The UK's daily deaths data is very similar to Italy's.\n")
+    f.write(f'If I use the Italian data for the next {s_end - s_start - 1} days,')
+    f.write(f' the UK will report {uk_projection.deaths.sum()} deaths on day {s_end} of the epidemic.\n')
+    f.write('\n')
+    f.write('Using the excess deaths scaling from above, that will translate into ')
+    f.write(f'**{(uk_projection.deaths.sum() * excess_deaths / reported_deaths):.0f}** Covid deaths total.\n')
+    f.write('\n')
+```
+
+```python
+with open('covid_summary.md', 'a') as f:
+    f.write('\n')
+    f.write('## Deaths doubling times\n')
+    f.write(f'Based on a 7-day moving average\n')
+    f.write('\n')
+    f.write('![Deaths doubling times](covid_doubling_times_7.png)\n')
+    f.write('\n')
+```
+
+```python
+with open('covid_summary.md', 'a') as f:
+    f.write('# Data sources\n')
+    f.write('\n')
+    f.write('> Covid data from [European Centre for Disease Prevention and Control](https://www.ecdc.europa.eu/en/publications-data/download-todays-data-geographic-distribution-covid-19-cases-worldwide)\n')
+    f.write('\n')    
+    f.write("""> Population data from:
+
+* [Office of National Statistics](https://www.ons.gov.uk/peoplepopulationandcommunity/birthsdeathsandmarriages/deaths/datasets/weeklyprovisionalfiguresondeathsregisteredinenglandandwales) (Endland and Wales) Weeks start on a Saturday.
+* [Northern Ireland Statistics and Research Agency](https://www.nisra.gov.uk/publications/weekly-deaths) (Northern Ireland). Weeks start on a Saturday. Note that the week numbers don't match the England and Wales data.
+* [National Records of Scotland](https://www.nrscotland.gov.uk/statistics-and-data/statistics/statistics-by-theme/vital-events/general-publications/weekly-and-monthly-data-on-births-and-deaths/weekly-data-on-births-and-deaths) (Scotland). Note that Scotland uses ISO8601 week numbers, which start on a Monday.""")
+    
+    f.write('\n\n')
+    f.write('> [Souce code available](https://git.njae.me.uk/?p=covid19.git;a=tree)\n')
+    f.write('\n') 
+
+```
+
+```python
+!pandoc -s covid_summary.md > covid_summary.html
+```
+
+```python
+!scp covid_summary.html neil@ogedei:/var/www/scripts.njae.me.uk/covid/index.html
+!scp covid_deaths_total_linear.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/
+!scp deaths-radar.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/
+!scp covid_deaths_per_day_7.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/
+!scp covid_doubling_times_7.png neil@ogedei:/var/www/scripts.njae.me.uk/covid/
+```
+
 ```python
 
 ```