diff --git a/dashboard_template.xhtml b/dashboard_template.xhtml index b5f6eb9..5b3b82f 100644 --- a/dashboard_template.xhtml +++ b/dashboard_template.xhtml @@ -14,24 +14,24 @@

- Bislang wurden {{ total_vaccinations }} Impfungen1 innerhalb von {{ days_since_start }} Tagen2 vorgenommen. - Das entspricht einem Anteil von {{ total_vaccinations_percentage }} % der Bevölkerung3. + Bislang wurden {{ '{:n}'.format(data_first_vaccination.total).replace('.', ' ') }} Erstimpfungen innerhalb von {{ '{:n}'.format(data_first_vaccination.days_since_start).replace('.', ' ') }} Tagen1 vorgenommen. + Das entspricht einem Anteil von {{ '{:.3n}'.format(data_first_vaccination.total_percentage) }} % der Bevölkerung2.

- Durchschnittlich fanden seit Start täglich {{ mean_vaccinations_daily }} Impfungen statt. - Mit dieser durchnittlichen Rate dauert es bis zum {{ mean_vaccinations_daily_herd_immunity }}, bis {{ herd_immunity }} %4 der Bevölkerung die erste Impfung erhalten haben, - und bis zum {{ mean_vaccinations_daily_done }} für 100 %. + Seit {{ '{:n}'.format(data_second_vaccination.days_since_start).replace('.', ' ') }} Tagen laufen die Zweitimpfungen. + Bislang wurden {{ '{:n}'.format(data_second_vaccination.total).replace('.', ' ') }} Zweitimpfungen verabreicht, das entspricht einem Anteil von {{ '{:.3n}'.format(data_second_vaccination.total_percentage) }} % der Bevölkerung.

- Am {{ last_date }} wurden {{ last_date_day_rate }} Impfungen vorgenommen. - Mit der Rate vom {{ last_date }} dauert es bis zum {{ last_date_day_rate_herd_immunity }} für {{ herd_immunity }} % und bis zum {{ last_date_day_rate_done }} für 100 %5. + Durchschnittlich fanden seit Start täglich {{ '{:n}'.format(data_first_vaccination['extrapolation_mean_all_time']['rate_int']).replace('.', ' ') }} Impfungen statt. + Mit dieser durchnittlichen Rate dauert es bis zum {{ data_first_vaccination['extrapolation_mean_all_time']['date_herd_immunity_str'] }}, bis {{ herd_immunity }} %3 der Bevölkerung die erste Impfung erhalten haben, + und bis zum {{ data_first_vaccination['extrapolation_mean_all_time']['date_done_str'] }} für 100 %.

- In den letzten sieben Tagen wurden durschnittlich {{ mean_vaccinations_last_seven_days }} Impfungen pro Tag vorgenommen. - Mit dieser Rate dauert es bis zum {{ mean_vaccinations_last_seven_days_herd_immunity }} für {{ herd_immunity }} % und bis zum {{ mean_vaccinations_last_seven_days_done }} für 100 %. + In den letzten sieben Tagen wurden durschnittlich {{ '{:n}'.format(data_first_vaccination['extrapolation_mean_seven_days']['rate_int']).replace('.', ' ') }} Impfungen pro Tag vorgenommen. + Mit dieser Rate dauert es bis zum {{ data_first_vaccination['extrapolation_mean_seven_days']['date_herd_immunity_str'] }} für {{ herd_immunity }} % und bis zum {{ data_first_vaccination['extrapolation_mean_seven_days']['date_done_str'] }} für 100 %.

-
+

Fragen und Antworten

@@ -160,6 +129,17 @@

Zum Archiv
+
+

Kann ich die Inhalte hier teilen?

+

+ Ja, das ist erlaubt, nach den Bedingungen der Creative Commons Namensnennung - Weitergabe unter gleichen Bedingungen 4.0 International (CC BY-SA 4.0). + Das heißt, dass du einen Hinweis auf den Ersteller (also mich) geben musst (bevorzugt per Link auf diese Seite), und dass Abwandlungen, die du hiervon erstellst, wieder unter ähnlich freien Bedingungen weitergegeben werden müssen. +

+

+ In den Plots stehen die nötigen Infos dafür oben mit drauf. + Ein Link wäre aber auch hier nett. +

+

Plots

@@ -203,17 +183,29 @@ Download als PDF +
+ + + +
+ Abbildung 4: + Tägliche Impfrate (Erst- und Zweitimpfung)
+ Download als PNG + Download als PDF +
+

Fußnoten

    -
  1. Gezählt werden verabreichte Dosen, unabhängig ob erste oder zweite Dosis.
  2. -
  3. Starttermin der Impfungen war der 27. Dezember 2020, der letzte Tag der Daten ist der {{ last_date }}.
  4. -
  5. Bevölkerungsstand vom 31. Dezember 2019: {{ einwohner_deutschland }}.
  6. -
  7. {{ herd_immunity }} % ist der Wert, bei dem aktuell von einer Herdenimmunität ausgegangen wird.
  8. -
  9. Die täglichen Impfraten unterliegen starken Schwankungen und sind daher wenig aussagekräftig.
  10. -
  11. Nicht alle Länder veröffentlichen alle in der Aufschlüsselung aufgelisteten Daten.
  12. +
  13. Starttermin der Erstimpfungen war der {{ data_first_vaccination.start_of_vaccination_date_str }} und {{ data_second_vaccination.start_of_vaccination_date_str }} war der Start für die Zweitimpfungen. Der letzte Tag der Daten ist der {{ data_first_vaccination.last_date_str }}.
  14. +
  15. Bevölkerungsstand vom 31. Dezember 2019: {{ einwohner_deutschland }}.
  16. +
  17. {{ herd_immunity }} % ist der Wert, bei dem aktuell von einer Herdenimmunität ausgegangen wird.
  18. + +
  19. Nicht alle Länder veröffentlichen alle in der Aufschlüsselung aufgelisteten Daten.
diff --git a/plot.py b/plot.py index bc77a9f..ceaba82 100644 --- a/plot.py +++ b/plot.py @@ -38,59 +38,82 @@ r = req.get('https://www.rki.de/DE/Content/InfAZ/N/Neuartiges_Coronavirus/Daten/ with open(data_filename, 'wb') as outfile: outfile.write(r.content) - +#data_filename = 'data/20210118151908_Impfquotenmonitoring.xlsx' rki_file = pd.read_excel(data_filename, sheet_name=None, engine='openpyxl') raw_data = rki_file['Impfungen_proTag'] -impfungen = raw_data[:-1].dropna() +impfungen = raw_data[:-1].dropna(subset=['Datum'])#.fillna(0) dates = impfungen['Datum'] -daily = impfungen['Gesamtzahl Impfungen'] -cumulative = np.cumsum(impfungen['Gesamtzahl Impfungen']) -total_vaccinations = int(np.sum(daily)) -total_vaccinations_percentage = float(total_vaccinations) / einwohner_deutschland +start_of_reporting_date = dates.iloc[0].date() -mean_vaccinations_daily = np.mean(daily) -mean_vaccinations_daily_int = int(np.round(mean_vaccinations_daily)) +def calculate_vaccination_data(data): + cumulative = np.cumsum(data) -to_be_vaccinated = einwohner_deutschland - total_vaccinations -days_extrapolated = int(np.ceil(to_be_vaccinated / mean_vaccinations_daily)) + total = int(np.sum(data)) + total_percentage = float(total) / einwohner_deutschland * 100 -extrapolated_dates = np.array([dates[0] + datetime.timedelta(days=i) for i in range(days_extrapolated)]) + mean_all_time = np.mean(data) + mean_seven_days = np.mean(data[-7:]) -mean_vaccinations_daily_done = extrapolated_dates[-1] -mean_vaccinations_daily_herd_immunity = extrapolated_dates[int(np.ceil(days_extrapolated * herd_immunity))] + to_be_vaccinated = einwohner_deutschland - total -days_extrapolated_with_todays_rate = int(np.ceil(to_be_vaccinated / daily.iloc[-1])) + last_date = dates.iloc[-1].date() + start_of_vaccination_date = dates[data.first_valid_index()].date() + days_since_start_of_vaccination = (last_date - start_of_vaccination_date).days + days_since_start_of_reporting = (last_date - start_of_reporting_date).days -last_date = dates.iloc[-1] + def extrapolate(rate, to_be_vaccinated): + days_extrapolated = int(np.ceil(to_be_vaccinated / rate)) + extrapolated_dates = np.array([dates[0] + datetime.timedelta(days=i) for i in range(days_extrapolated)]) -last_date_day_rate = daily.iloc[-1] -last_date_day_rate_done = dates[0] + datetime.timedelta(days=days_extrapolated_with_todays_rate) -last_date_day_rate_herd_immunity = dates[0] + datetime.timedelta(days=int(np.ceil(days_extrapolated_with_todays_rate * herd_immunity))) + date_done = extrapolated_dates[-1] + date_herd_immunity = extrapolated_dates[int(np.ceil(days_extrapolated * herd_immunity))] + + extrapolated_vaccinations = total + rate * range(-days_since_start_of_reporting, days_extrapolated - days_since_start_of_reporting) + + return { + 'rate': rate, + 'rate_int': int(np.round(rate)), + 'days_extrapolated': days_extrapolated, + 'dates': extrapolated_dates, + 'date_done': date_done, + 'date_done_str': date_done.strftime('%d. %B %Y'), + 'date_herd_immunity': date_herd_immunity, + 'date_herd_immunity_str': date_herd_immunity.strftime('%d. %B %Y'), + 'extrapolated_vaccinations': extrapolated_vaccinations + } -extrapolated_vaccinations = mean_vaccinations_daily * range(1, days_extrapolated + 1) + extrapolation_mean_all_time = extrapolate(mean_all_time, to_be_vaccinated) + extrapolation_last_rate = extrapolate(data.iloc[-1], to_be_vaccinated) + extrapolation_mean_seven_days = extrapolate(mean_seven_days, to_be_vaccinated) -days_since_start = (dates.iloc[-1].date() - dates[0].date()).days + mean_vaccination_rates_daily = np.round(cumulative / range(1, len(cumulative) + 1)) -mean_vaccinations_last_seven_days = np.mean(daily[-7:]) -mean_vaccinations_last_seven_days_int = int(np.round(mean_vaccinations_last_seven_days)) - -days_extrapolated_last_seven_days = int(np.ceil(to_be_vaccinated / mean_vaccinations_last_seven_days)) - -extrapolated_vaccinations_last_seven_days = total_vaccinations + mean_vaccinations_last_seven_days * range(-days_since_start, days_extrapolated - days_since_start) - -mean_vaccinations_last_seven_days_done = dates.iloc[-1] + datetime.timedelta(days=days_extrapolated_last_seven_days) -mean_vaccinations_last_seven_days_herd_immunity = dates.iloc[-1] + datetime.timedelta(days=int(np.ceil(days_extrapolated_last_seven_days * herd_immunity))) + return { + 'daily': data, + 'cumulative': cumulative, + 'total': total, + 'total_percentage': total_percentage, + 'to_be_vaccinated': to_be_vaccinated, + 'last_date': last_date, + 'last_date_str': last_date.strftime('%d. %B %Y'), + 'days_since_start': days_since_start_of_vaccination + 1, # Shift from zero to one-based-index + 'start_of_vaccination_date': start_of_vaccination_date, + 'start_of_vaccination_date_str': start_of_vaccination_date.strftime('%d. %B %Y'), + 'extrapolation_mean_all_time': extrapolation_mean_all_time, + 'extrapolation_last_rate': extrapolation_last_rate, + 'extrapolation_mean_seven_days': extrapolation_mean_seven_days, + 'mean_vaccination_rates_daily': mean_vaccination_rates_daily + } - -mean_vaccinations_daily_up_to_date = np.round(cumulative / range(1, len(cumulative) + 1)) - +data_first_vaccination = calculate_vaccination_data(impfungen['Erstimpfung']) +data_second_vaccination = calculate_vaccination_data(impfungen['Zweitimpfung']) # Stand aus Daten auslesen #stand = dates.iloc[-1] @@ -107,11 +130,14 @@ print_stand = stand_date.isoformat() filename_stand = stand_date.strftime("%Y%m%d%H%M%S") +''' + # Infos der einzelnen Länder details_sheet_name = (set(rki_file.keys()) - {'Erläuterung', 'Impfungen_proTag'}).pop() details_sheet = rki_file[details_sheet_name] +regionalcodes = details_sheet['RS'].iloc[0:17] land_names = details_sheet['Bundesland'].iloc[0:17] total_vaccinations_by_land = details_sheet['Impfungen kumulativ'].iloc[0:17] @@ -125,8 +151,37 @@ vaccination_reason_oldhome_by_land = details_sheet['Pflegeheim-bewohnerIn*'].ilo details_per_land = {} details_per_land_formatted = {} +# Regionalcodes der Länder zu Abkürzung und Name (Plus gesamt) +laendernamen = [ + ('SH', 'Schleswig-Holstein'), + ('HH', 'Hamburg'), + ('NI', 'Niedersachsen'), + ('HB', 'Bremen'), + ('NW', 'Nordrhein-Westfalen'), + ('HE', 'Hessen'), + ('RP', 'Rheinland-Pfalz'), + ('BW', 'Baden-Württemberg'), + ('BY', 'Bayern'), + ('SL', 'Saarland'), + ('BE', 'Berlin'), + ('BB', 'Brandenburg'), + ('MV', 'Mecklenburg-Vorpommern'), + ('SN', 'Sachsen'), + ('ST', 'Sachsen-Anhalt'), + ('TH', 'Thüringen'), + ('𝚺', 'Gesamt') +] + def row_to_details(i): + regionalcode = regionalcodes[i] if i != 16 else 16 + + print(laendernamen[regionalcode]) + + shortname, name = laendernamen[regionalcode] + return { + 'name': name, + 'shortname': shortname, 'total_vaccinations': int(total_vaccinations_by_land[i]), 'total_vaccinations_percentage': vaccination_per_mille_by_land[i] / 10, 'vaccination_reason_age': int(vaccination_reason_age_by_land[i]), @@ -140,7 +195,15 @@ def row_to_details(i): } def row_to_details_formatted(i): + regionalcode = regionalcodes[i] if i != 16 else 16 + + print(laendernamen[regionalcode]) + + shortname, name = laendernamen[regionalcode] + return { + 'name': name, + 'shortname': shortname, 'total_vaccinations': '{:n}'.format(int(total_vaccinations_by_land[i])).replace('.', ' '), 'total_vaccinations_percentage': '{:.3n}'.format(np.round(vaccination_per_mille_by_land[i] / 10, 2)), 'vaccination_reason_age': '{:n}'.format(int(vaccination_reason_age_by_land[i])).replace('.', ' '), @@ -162,6 +225,13 @@ for i in range(len(land_names) - 1): details_total = row_to_details(16) details_total_formatted = row_to_details_formatted(16) +''' + + + + + + archive_folder = site_folder + 'archive/' + filename_stand if os.path.isdir(archive_folder): @@ -169,6 +239,9 @@ if os.path.isdir(archive_folder): else: os.mkdir(archive_folder) + + + def plot_extrapolation_portion(percentage): print_percentage = int(percentage * 100) @@ -183,26 +256,38 @@ def plot_extrapolation_portion(percentage): plt.title( - 'Tägliche Impfquote, kumulierte Impfungen und lineare Extrapolation bis {:n} % der Bevölkerung Deutschlands\n' - 'Erstellung: {}, Datenquelle: RKI, Stand: {}\n' - 'Impfungen gesamt: {:n} ({:n} %), Durchschnittliche Impfrate: {:n} Impfungen/Tag'.format( + 'Tägliche Impfrate (Erst- und Zweitimpfung), kumulierte Impfungen und lineare Extrapolation bis {:n} % der Bevölkerung Deutschlands\n' + 'Datenquelle: RKI, Stand: {}. Erstellung: {}, Ersteller: Benedikt Bastin, Lizenz: CC BY-SA 4.0\n' + 'Erstimpfungen: {:n} ({:n} %), Durchschnittliche Impfrate: {:n} Impfungen/Tag (läuft seit {:n} Tagen)\n' + 'Zweitimpfungen: {:n} ({:n} %), Durchschnittliche Impfrate: {:n} Impfungen/Tag (läuft seit {:n} Tagen)'.format( print_percentage, - print_today, print_stand, - total_vaccinations, np.round(total_vaccinations_percentage * 100, 2), mean_vaccinations_daily_int + print_stand, print_today, + data_first_vaccination['total'], np.round(data_first_vaccination['total_percentage'], 2), data_first_vaccination['extrapolation_mean_all_time']['rate'], data_first_vaccination['days_since_start'], + data_second_vaccination['total'], np.round(data_second_vaccination['total_percentage'], 2), data_second_vaccination['extrapolation_mean_all_time']['rate'], data_second_vaccination['days_since_start'] ) ) ax2 = ax.twinx() - ax.bar(dates, daily, label='Tägliche Impfungen', color='blue') - ax.plot(dates, mean_vaccinations_daily_up_to_date, color='violet', label='Durchschnittliche Impfquote\nbis zu diesem Tag (inkl.)') + ax.bar(dates, data_first_vaccination['daily'], label='Tägliche Erstimpfungen', color='blue') + ax.bar(dates, data_second_vaccination['daily'], label='Tägliche Zweitimpfungen', color='lightblue') + + ax.plot(dates, data_first_vaccination['mean_vaccination_rates_daily'], color='violet', label='Durchschnittliche Erstimpfrate\nbis zu diesem Tag (inkl.)') + ax.plot(dates, data_second_vaccination['mean_vaccination_rates_daily'], color='magenta', label='Durchschnittliche Zweitimpfrate\nbis zu diesem Tag (inkl.)') ax2.set_ylim([0, einwohner_deutschland * percentage]) - ax2.set_xlim(xmax=dates[0] + datetime.timedelta(days=percentage * days_extrapolated)) + ax2.set_xlim(xmax=dates[0] + datetime.timedelta(days=percentage * data_first_vaccination['extrapolation_mean_all_time']['days_extrapolated'])) ax2.grid(True) - ax2.plot(dates, cumulative, color='red', label='Kumulierte Impfungen') - ax2.plot(extrapolated_dates, extrapolated_vaccinations, color='orange', label='Extrap. kumulierte Impfungen (Ø gesamt)\n{:n} Impfungen/Tag'.format(mean_vaccinations_daily_int)) - ax2.plot(extrapolated_dates, extrapolated_vaccinations_last_seven_days, color='goldenrod', label='Extrap. kumulierte Impfungen (Ø 7 Tage)\n{:n} Impfungen/Tag'.format(mean_vaccinations_last_seven_days_int)) + + ax2.plot(dates, data_first_vaccination['cumulative'], color='red', label='Kumulierte Erstimpfungen') + ax2.plot(dates, data_second_vaccination['cumulative'], color='indianred', label='Kumulierte Zweitimpfungen') + + ax2.plot(data_first_vaccination['extrapolation_mean_all_time']['dates'], data_first_vaccination['extrapolation_mean_all_time']['extrapolated_vaccinations'], color='orange', label='Extrap. kumulierte Erstimpfungen (Ø gesamt)\n{:n} Impfungen/Tag'.format(data_first_vaccination['extrapolation_mean_all_time']['rate_int'])) + ax2.plot(data_first_vaccination['extrapolation_mean_seven_days']['dates'], data_first_vaccination['extrapolation_mean_seven_days']['extrapolated_vaccinations'], color='goldenrod', label='Extrap. kumulierte Erstimpfungen (Ø 7 Tage)\n{:n} Impfungen/Tag'.format(data_first_vaccination['extrapolation_mean_seven_days']['rate_int'])) + ax2.plot() + + ax2.plot(data_second_vaccination['extrapolation_mean_all_time']['dates'], data_second_vaccination['extrapolation_mean_all_time']['extrapolated_vaccinations'], color='orange', label='Extrap. kumulierte Zweitimpfungen (Ø gesamt)\n{:n} Impfungen/Tag'.format(data_second_vaccination['extrapolation_mean_all_time']['rate_int'])) + ax2.plot(data_second_vaccination['extrapolation_mean_seven_days']['dates'], data_second_vaccination['extrapolation_mean_seven_days']['extrapolated_vaccinations'], color='goldenrod', label='Extrap. kumulierte Zweitimpfungen (Ø 7 Tage)\n{:n} Impfungen/Tag'.format(data_second_vaccination['extrapolation_mean_seven_days']['rate_int'])) #ax2.plot() ax.legend(loc='upper left') @@ -211,7 +296,7 @@ def plot_extrapolation_portion(percentage): ax.set_xlabel('Datum') ax.set_ylabel('Tägliche Impfungen') - ax2.legend(loc='center right') + ax2.legend(loc='lower right') ax2.get_yaxis().get_major_formatter().set_scientific(False) # Estimated percentage for herd immunity @@ -229,10 +314,54 @@ def plot_extrapolation_portion(percentage): plot_extrapolation_portion(0.1) -plot_extrapolation_portion(0.7) +#plot_extrapolation_portion(0.7) plot_extrapolation_portion(1.0) + +def plot_vaccination_bar_graph_total_time(): + + archive_plot_filename = '{}/vaccination_bar_graph_total_time'.format(archive_folder) + latest_plot_filename = '{}/vaccination_bar_graph_total_time'.format(site_folder) + + if os.path.isfile(archive_plot_filename + '.pdf'): + print('Plot {} already exists'.format(archive_plot_filename)) + return + + fig, ax = plt.subplots(1) + + + plt.title( + 'Tägliche Impfrate (Erst- und Zweitimpfung)\n' + 'Datenquelle: RKI, Stand: {}. Erstellung: {}, Ersteller: Benedikt Bastin, Lizenz: CC BY-SA 4.0\n'.format( + print_stand, print_today + ) + ) + + ax.grid() + + ax.bar(dates, data_first_vaccination['daily'], label='Tägliche Erstimpfungen', color='blue') + ax.bar(dates, data_second_vaccination['daily'], label='Tägliche Zweitimpfungen', color='lightblue', bottom=data_first_vaccination['daily']) + + ax.set_ylim([0, np.max(data_first_vaccination['daily']) + np.max(data_second_vaccination['daily'])]) + + ax.legend(loc='upper left') + ax.get_yaxis().get_major_formatter().set_scientific(False) + + ax.set_xlabel('Datum') + ax.set_ylabel('Tägliche Impfungen') + + + plt.savefig(archive_plot_filename + '.pdf') + plt.savefig(archive_plot_filename + '.png') + plt.savefig(latest_plot_filename + '.pdf') + plt.savefig(latest_plot_filename + '.png') + plt.close() + + print('Created plot {} as pdf and png'.format(archive_plot_filename)) + +plot_vaccination_bar_graph_total_time() + def render_dashboard(): dashboard_filename = 'site/index.xhtml' dashboard_archive_filename = 'site/archive/{}/index.xhtml'.format(filename_stand) @@ -264,21 +393,10 @@ def render_dashboard(): filename_stand = filename_stand, einwohner_deutschland = '{:n}'.format(einwohner_deutschland).replace('.', ' '), herd_immunity = '{:n}'.format(int(herd_immunity * 100)), - total_vaccinations = '{:n}'.format(total_vaccinations).replace('.', ' '), - total_vaccinations_percentage = '{:.3n}'.format(total_vaccinations_percentage * 100), - days_since_start = days_since_start, - last_date = last_date.strftime(df), - last_date_day_rate = '{:n}'.format(last_date_day_rate).replace('.', ' '), - mean_vaccinations_daily = '{:n}'.format(mean_vaccinations_daily_int).replace('.', ' '), - mean_vaccinations_daily_herd_immunity = mean_vaccinations_daily_herd_immunity.strftime(df), - mean_vaccinations_daily_done = mean_vaccinations_daily_done.strftime(df), - last_date_day_rate_herd_immunity = last_date_day_rate_herd_immunity.strftime(df), - last_date_day_rate_done = last_date_day_rate_done.strftime(df), - mean_vaccinations_last_seven_days = '{:n}'.format(mean_vaccinations_last_seven_days_int).replace('.', ' '), - mean_vaccinations_last_seven_days_herd_immunity = mean_vaccinations_last_seven_days_herd_immunity.strftime(df), - mean_vaccinations_last_seven_days_done = mean_vaccinations_last_seven_days_done.strftime(df), - details_per_land = dict(sorted(details_per_land_formatted.items(), key=lambda item: item[0])), - details_total = details_total_formatted + data_first_vaccination = data_first_vaccination, + data_second_vaccination = data_second_vaccination, + #details_per_land = dict(sorted(details_per_land_formatted.items(), key=lambda item: item[0])), + #details_total = details_total_formatted ).dump('site/index.xhtml') shutil.copyfile(dashboard_filename, dashboard_archive_filename)