Jedes Mal, wenn ich die Nachrichten über die Anzahl neuer Koronavirusinfektionen sah, dachte ich: "Ich möchte, dass Sie mir mehr über die Aufteilung der Altersgruppe erzählen", aber ich erfuhr, dass die Stadtregierung von Tokio Daten über positive Patienten veröffentlicht hat. ..
Hier werden wir vorstellen, wie die von der Stadtregierung von Tokio veröffentlichten Daten mit Python und Pandas, Seaborn, Matplotlib, analysiert und visualisiert werden.
Der Hauptpunkt dieses Artikels sind nicht die Vorhersagen und Empfehlungen, dass "dies in Zukunft geschehen wird" und "diese Art von Maßnahmen ergriffen werden sollten", sondern "dies erleichtert die Visualisierung der Daten, sodass jeder sie ausprobieren sollte". Wenn Sie es selbst versuchen, werden Sie Ihr Verständnis vertiefen. Probieren Sie es also aus.
Beachten Sie, dass Matplotlib, wenn Sie sich besonders mit Details wie dem Diagrammlayout und dem Achsenformat befassen, eine mühsame Verarbeitung erfordert, sodass ich hier nicht auf Details eingehen werde (nur eine kleine Berührung am Ende). Anstatt ein ansprechendes Diagramm für eine umfassende Offenlegung zu erstellen, besteht das Ziel darin, die Daten zu visualisieren und Trends selbst zu erkennen.
Beispielcode ist auch auf GitHub verfügbar. Das Jupyter-Notizbuch (.ipynb
) ist leichter zu lesen, lesen Sie es daher ebenfalls.
Die positiven Patientendaten für Tokio werden unten veröffentlicht.
Sie erreichen es über den Link "Get open data" auf Tokios neuer Website zur Kontrolle von Koronavireninfektionen.
Mit Blick auf Verlauf scheint es, dass es an Wochentagen von 10 auf 15 Uhr aktualisiert wird.
Nachfolgend finden Sie eine Liste der Websites, die die Websites für Gegenmaßnahmen in Tokio gegabelt haben.
Einige Websites, wie z. B. Tokio, enthalten Links zu offenen Daten. Nachfolgend finden Sie Beispiele aus den Präfekturen Hokkaido und Kanagawa.
Selbst wenn auf der Website kein Link vorhanden ist, sollten die Daten selbst irgendwo veröffentlicht werden, damit Sie sie durch Suchen finden können.
Der folgende Beispielcode verwendet Daten aus Tokio. Daten anderer Präfekturen können unterschiedliche Elemente haben, aber die Grundbehandlung ist dieselbe.
Darüber hinaus gibt es als Daten zum neuen Coronavirus aggregierte Daten wie die Anzahl der durchgeführten inländischen PCR-Tests, die Anzahl der positiven Ergebnisse, die Anzahl der im Krankenhaus befindlichen Personen und die Anzahl der vom Ministerium für Gesundheit, Arbeit und Soziales angekündigten Todesfälle.
Die Versionen jeder Bibliothek und von Python selbst im folgenden Beispielcode lauten wie folgt. Beachten Sie, dass sich verschiedene Versionen möglicherweise unterschiedlich verhalten.
import math
import sys
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
print(pd.__version__)
# 1.0.5
print(mpl.__version__)
# 3.3.0
print(sns.__version__)
# 0.10.1
print(sys.version)
# 3.8.5 (default, Jul 21 2020, 10:48:26)
# [Clang 11.0.3 (clang-1103.0.32.62)]
Geben Sie den Pfad zur heruntergeladenen CSV-Datei in "pd.read_csv ()" an und lesen Sie ihn als "DataFrame". Als Beispiel dienen die Daten bis zum 31. Juli 2020.
df = pd.read_csv('data/130001_tokyo_covid19_patients_20200731.csv')
Sie können die URL direkt im Argument von "pd.read_csv ()" angeben, aber es ist sicherer, sie lokal herunterzuladen, da in der Phase von Versuch und Irrtum mehrmals vergeblich darauf zugegriffen wird.
# df = pd.read_csv('https://stopcovid19.metro.tokyo.lg.jp/data/130001_tokyo_covid19_patients.csv')
Die Anzahl der Zeilen / Spalten und die Daten am Anfang und Ende sind wie folgt.
print(df.shape)
# (12691, 16)
print(df.head())
#Nein Nationaler Code der öffentlichen Organisation Präfekturname Stadtbezirk Name der Stadt / des Dorfes veröffentlicht_Datumsbeginn_Datum Patient_Wohnort Patient_Alter Patient_Sex\
#0 1 130001 Tokyo NaN 2020-01-24 Fr NaN Wuhan City, Provinz Hubei Männlich in seinen 40ern
#1 2 130001 Tokyo NaN 2020-01-25 Sa NaN Wuhan City, Provinz Hubei Frauen in den Dreißigern
#2 3 130001 Tokyo NaN 2020-01-30 Do NaN Changsha Stadt, Provinz Hunan Frauen in ihren 30ern
#3 4 130001 Tokyo NaN 2020-02-13 Do NaN Männlich in seinen 70ern in Tokio
#4 5 130001 Tokyo NaN 2020-02-14 Fr NaN Frauen in den Fünfzigern in Tokio
#
#geduldig_Attribut Patient_Zustand Patient_Symptompatient_Reiseverlaufsflagge Bemerkungen Entladene Flagge
# 0 NaN NaN NaN NaN NaN 1.0
# 1 NaN NaN NaN NaN NaN 1.0
# 2 NaN NaN NaN NaN NaN 1.0
# 3 NaN NaN NaN NaN NaN 1.0
# 4 NaN NaN NaN NaN NaN 1.0
print(df.tail())
#Nein Nationaler Code der öffentlichen Organisation Präfekturname Stadtbezirk Name der Stadt / des Dorfes veröffentlicht_Datumsbeginn_Datum Patient_Wohnort Patient_Alter\
#12686 12532 130001 Tokyo NaN 2020-07-31 Fr NaN NaN 70er Jahre
#12687 12558 130001 Tokyo NaN 2020-07-31 Fr NaN NaN 70er Jahre
#12688 12563 130001 Tokyo NaN 2020-07-31 Fr NaN NaN 70er Jahre
#12689 12144 130001 Tokyo NaN 2020-07-31 Fr NaN NaN 80er Jahre
#12690 12517 130001 Tokyo NaN 2020-07-31 Fr NaN NaN 80er Jahre
#
#geduldig_Geschlechtspatientin_Attribut Patient_Zustand Patient_Symptompatient_Reiseverlaufsflagge Bemerkungen Entladene Flagge
#12686 Männliches NaN NaN NaN NaN NaN NaN
#12687 Männliches NaN NaN NaN NaN NaN NaN
#12688 Männliches NaN NaN NaN NaN NaN NaN
#12689 Weibliches NaN NaN NaN NaN NaN NaN NaN
#12690 Männliches NaN NaN NaN NaN NaN NaN
Wenn kategoriale Daten wie diese die Hauptdaten sind, können Sie sich mithilfe von Methoden wie "count ()", "nunique ()", "unique ()" und "value_counts ()" leicht einen Überblick verschaffen.
count ()
gibt die Anzahl der Elemente zurück, bei denen es sich nicht um den fehlenden Wert NaN
handelt. Es ist ersichtlich, dass detaillierte Informationen wie Namen, Symptome und Attribute von Stadt / Gemeinde / Stadt / Dorf nicht bekannt gegeben werden (keine Daten), wahrscheinlich aus Gründen des Datenschutzes.
print(df.count())
# No 12691
#National Local Public Organization Code 12691
#Präfekturname 12691
#Name der Stadt 0
#Veröffentlicht_Datum 12691
#Tag 12691
#Beginn_Datum 0
#geduldig_Wohnort 12228
#geduldig_Alter 12691
#geduldig_Geschlecht 12691
#geduldig_Attribut 0
#geduldig_Zustand 0
#geduldig_Symptom 0
#geduldig_Reiseverlauf Flagge 0
#Bemerkung 0
#Entladene Flagge 7186
# dtype: int64
nunique ()
gibt die Anzahl der Datentypen zurück. Da es sich um die Daten von Tokio handelt, sind der nationale Kommunalcode und der Name der Präfektur alle gleich.
print(df.nunique())
# No 12691
#Nationaler Code der lokalen öffentlichen Organisation 1
#Präfekturname 1
#Name der Stadt 0
#Veröffentlicht_Datum 164
#Tag 7
#Beginn_Datum 0
#geduldig_Wohnort 8
#geduldig_Alter 13
#geduldig_Geschlecht 5
#geduldig_Attribut 0
#geduldig_Zustand 0
#geduldig_Symptom 0
#geduldig_Reiseverlauf Flagge 0
#Bemerkung 0
#Entladene Flagge 1
# dtype: int64
Für jede Spalte (= Serie
) können Sie die eindeutigen Elemente und ihre Anzahl (Auftrittshäufigkeit) mit unique ()
, value_counts ()
überprüfen.
print(df['geduldig_Residenz'].unique())
# ['Stadt Wuhan, Provinz Hubei' 'Stadt Changsha, Provinz Hunan' 'In Tokio' 'Ausserhalb der Stadt' '―' 'Nachforschungen anstellen' '-' "'-" nan]
print(df['geduldig_Residenz'].value_counts(dropna=False))
#Tokio 11271
#Außerhalb von Tokio 531
# NaN 463
# ― 336
#In Untersuchung 85
#Stadt Wuhan, Provinz Hubei 2
#Stadt Changsha, Provinz Hunan 1
# '- 1
# - 1
# Name:geduldig_Residenz, dtype: int64
print(df['geduldig_Sex'].unique())
# ['männlich' 'Weiblich' "'-" '―' 'Unbekannt']
print(df['geduldig_Sex'].value_counts())
#Männlich 7550
#Weiblich 5132
# '- 7
#Unbekannt 1
# ― 1
# Name:geduldig_Sex, dtype: int64
Dieses Mal werden wir das Analyseziel auf das Veröffentlichungsdatum, das Alter des Patienten und die entlassene Flagge eingrenzen. Ändern Sie der Einfachheit halber den Spaltennamen mit "rename ()".
df = df[['Veröffentlicht_Datum', 'geduldig_Alter', 'Entladene Flagge']].copy()
df.rename(columns={'Veröffentlicht_Datum': 'date_str', 'geduldig_Alter': 'age_org', 'Entladene Flagge': 'discharged'},
inplace=True)
print(df)
# date_str age_org discharged
# 0 2020-01-24 40s 1.0
# 1 2020-01-25 30s 1.0
# 2 2020-01-30 30s 1.0
# 3 2020-02-13 70er Jahre 1.0
# 4 2020-02-14 50er Jahre 1.0
# ... ... ... ...
# 12686 2020-07-31 70s NaN
# 12687 2020-07-31 70s NaN
# 12688 2020-07-31 70s NaN
# 12689 2020-07-31 80er NaN
# 12690 2020-07-31 80er NaN
#
# [12691 rows x 3 columns]
Der Grund für die Verwendung von "copy ()" hier ist, "SettingWithCopyWarning" zu verhindern. In diesem Fall werden die Daten nicht aktualisiert, sodass es kein Problem gibt, wenn Sie sie in Ruhe lassen.
In der Ära-Spalte enthält sie Daten wie "unbekannt" und "-".
print(df['age_org'].unique())
# ['Vierziger Jahre' '30er Jahre' '70er Jahre' '50er Jahre' '60er Jahre' '80er Jahre' '20er Jahre' 'Unter 10 Jahren' '90er Jahre' '10er' '100 Jahre und älter'
# 'Unbekannt' "'-"]
print(df['age_org'].value_counts())
#20s 4166
#30s 2714
#40er Jahre 1741
#50er Jahre 1362
#60er Jahre 832
#70er Jahre 713
#80er 455
#Teen 281
#90er Jahre 214
#Unter 10 Jahren 200
#Unbekannt 6
#100 Jahre und älter 5
# '- 2
# Name: age_org, dtype: int64
Da die Anzahl klein ist, werde ich sie hier ausschließen.
df = df[~df['age_org'].isin(['Unbekannt', "'-"])]
print(df)
# date_str age_org discharged
# 0 2020-01-24 40s 1.0
# 1 2020-01-25 30s 1.0
# 2 2020-01-30 30s 1.0
# 3 2020-02-13 70er Jahre 1.0
# 4 2020-02-14 50er Jahre 1.0
# ... ... ... ...
# 12686 2020-07-31 70s NaN
# 12687 2020-07-31 70s NaN
# 12688 2020-07-31 70s NaN
# 12689 2020-07-31 80er NaN
# 12690 2020-07-31 80er NaN
#
# [12683 rows x 3 columns]
print(df['age_org'].unique())
# ['Vierziger Jahre' '30er Jahre' '70er Jahre' '50er Jahre' '60er Jahre' '80er Jahre' '20er Jahre' 'Unter 10 Jahren' '90er Jahre' '10er' '100 Jahre und älter']
Da die Alterseinteilung in Ordnung ist, machen Sie es etwas rauer. Die gesamte rechte Seite ist in Klammern "()" eingeschlossen, da sie in der Mitte bricht.
df['age'] = (
df['age_org'].replace(['Unter 10 Jahren', '10er'], '0-19')
.replace(['20er Jahre', '30er Jahre'], '20-39')
.replace(['Vierziger Jahre', '50er Jahre'], '40-59')
.replace(['60er Jahre', '70er Jahre', '80er Jahre', '90er Jahre', '100 Jahre und älter'], '60-')
)
print(df['age'].unique())
# ['40-59' '20-39' '60-' '0-19']
print(df['age'].value_counts())
# 20-39 6880
# 40-59 3103
# 60- 2219
# 0-19 481
# Name: age, dtype: int64
Die Spalte "Datum und Uhrzeit" (Veröffentlichungsdatum) "date_str" ist eine Zeichenfolge. Fügen Sie für die zukünftige Verarbeitung die Spalte "Datum" hinzu, die in den Typ "datetime64 [ns]" konvertiert wurde.
df['date'] = pd.to_datetime(df['date_str'])
print(df.dtypes)
# date_str object
# age_org object
# discharged float64
# age object
# date datetime64[ns]
# dtype: object
Dies ist das Ende der Vorverarbeitung. Von hier aus wird ein Beispiel für die tatsächliche Analyse und Visualisierung von Daten gezeigt.
Hier betrachten wir Veränderungen in der Anzahl neuer positiver Patienten nach Altersgruppen. Die Gesamtzahl der neuen positiven Patienten wird am Ende als Beispiel für die Verarbeitung mit Matplotlib beschrieben.
Verwenden Sie pd.crosstab ()
, um Datum und Uhrzeit (Veröffentlichungsdatum) und Alter zu kreuzen.
df_ct = pd.crosstab(df['date'], df['age'])
print(df_ct)
# age 0-19 20-39 40-59 60-
# date
# 2020-01-24 0 0 1 0
# 2020-01-25 0 1 0 0
# 2020-01-30 0 1 0 0
# 2020-02-13 0 0 0 1
# 2020-02-14 0 0 1 1
# ... ... ... ... ...
# 2020-07-27 5 79 34 13
# 2020-07-28 13 168 65 20
# 2020-07-29 9 160 56 25
# 2020-07-30 11 236 83 37
# 2020-07-31 10 332 82 39
#
# [164 rows x 4 columns]
print(type(df_ct.index))
# <class 'pandas.core.indexes.datetimes.DatetimeIndex'>
Die in den Typ "datetime64 [ns]" konvertierte Spalte wird zu einem neuen Index und wird als "DatetimeIndex" behandelt. Beachten Sie, dass selbst wenn die Ausgabe identisch ist und Sie einen Zeichenfolgentyp mit Datum und Uhrzeit angeben, dies nicht "DatetimeIndex" ist.
Wöchentlich mit resample ()
aggregieren. resample ()
kann nur mit DatetimeIndex
ausgeführt werden.
df_ct_week = df_ct.resample('W', label='left').sum()
print(df_ct_week)
# age 0-19 20-39 40-59 60-
# date
# 2020-01-19 0 1 1 0
# 2020-01-26 0 1 0 0
# 2020-02-02 0 0 0 0
# 2020-02-09 0 2 5 9
# 2020-02-16 0 1 3 6
# 2020-02-23 0 2 3 5
# 2020-03-01 2 5 9 9
# 2020-03-08 0 5 10 11
# 2020-03-15 0 10 27 12
# 2020-03-22 7 100 88 102
# 2020-03-29 16 244 198 148
# 2020-04-05 21 421 369 271
# 2020-04-12 30 350 375 280
# 2020-04-19 32 286 267 264
# 2020-04-26 29 216 165 260
# 2020-05-03 7 105 69 120
# 2020-05-10 2 46 16 46
# 2020-05-17 3 22 10 15
# 2020-05-24 4 43 16 21
# 2020-05-31 2 89 34 22
# 2020-06-07 5 113 17 26
# 2020-06-14 6 177 29 28
# 2020-06-21 10 236 65 23
# 2020-06-28 34 460 107 51
# 2020-07-05 79 824 191 68
# 2020-07-12 66 1006 295 117
# 2020-07-19 78 1140 414 171
# 2020-07-26 48 975 320 134
Visualisiert mit plot ()
. Sie können ganz einfach ein gestapeltes Balkendiagramm erstellen.
df_ct_week[:-1].plot.bar(stacked=True)
Die Daten in der letzten Zeile (letzte Woche) werden durch "[: -1]" ausgeschlossen. Diese Daten schließen die letzte Woche aus, da sie den Samstag (1. August 2020) nicht enthalten und nicht zum Vergleich mit anderen Wochen geeignet sind.
Das Jupyter-Notizbuch zeigt das Diagramm in der Ausgabezelle an. Wenn Sie es als Bilddatei speichern möchten, verwenden Sie plt.savefig ()
. Sie können auch mit der rechten Maustaste klicken, um die Ausgabe des Jupyter-Notizbuchs zu speichern.
plt.figure()
df_ct_week[:-1].plot.bar(stacked=True)
plt.savefig('image/bar_chart.png', bbox_inches='tight')
plt.close('all')
Der Zustand des Auftretens ist unbekannt, aber es gab ein Problem, dass die Beschriftung der X-Achse beim Speichern abgeschnitten wurde. Beziehen Sie sich auf Folgendes und setzen Sie "bbox_inches =" tight ", um das Problem zu lösen.
Wenn Sie ein Balkendiagramm wie im obigen Beispiel erstellen, wird die Uhrzeit auf der Beschriftung der X-Achse angezeigt. Die einfachste Lösung besteht darin, den Index in eine Zeichenfolge in einem beliebigen Format zu konvertieren.
df_ct_week_str = df_ct_week.copy()
df_ct_week_str.index = df_ct_week_str.index.strftime('%Y-%m-%d')
df_ct_week_str[:-1].plot.bar(stacked=True, figsize=(8, 4))
Standardisieren Sie das Ganze und sehen Sie den Übergang des Altersverhältnisses. T
ist die Translokation (Zeilen und Spalten tauschen). Sie kann standardisiert werden, indem Sie sie transponieren, durch den Gesamtwert dividieren, erneut verschieben und auf den ursprünglichen Wert zurücksetzen.
Die meisten jungen Menschen (20-30 Jahre) haben seit Juni geschlossen, aber in letzter Zeit steigt der Anteil der Menschen mittleren Alters (40 Jahre und älter).
df_ct_week_str_norm = (df_ct_week_str.T / df_ct_week_str.sum(axis=1)).T
Die Veränderungen zwischen jungen Menschen (20-30 Jahre) und älteren Menschen (60 Jahre und darüber hinaus) sind wie folgt. Auch die absolute Zahl älterer Menschen ist Ende März auf das Niveau gestiegen.
df_ct_week_str[:-1][['20-39', '60-']].plot.bar(figsize=(8, 4))
Berechnen Sie die Veränderung gegenüber der Vorwoche, um den Impuls der Ausbreitung der Infektion zu sehen.
Die Daten können durch "shift ()" verschoben und geteilt werden.
df_week_ratio = df_ct_week / df_ct_week.shift()
print(df_week_ratio)
# age 0-19 20-39 40-59 60-
# date
# 2020-01-19 NaN NaN NaN NaN
# 2020-01-26 NaN 1.000000 0.000000 NaN
# 2020-02-02 NaN 0.000000 NaN NaN
# 2020-02-09 NaN inf inf inf
# 2020-02-16 NaN 0.500000 0.600000 0.666667
# 2020-02-23 NaN 2.000000 1.000000 0.833333
# 2020-03-01 inf 2.500000 3.000000 1.800000
# 2020-03-08 0.000000 1.000000 1.111111 1.222222
# 2020-03-15 NaN 2.000000 2.700000 1.090909
# 2020-03-22 inf 10.000000 3.259259 8.500000
# 2020-03-29 2.285714 2.440000 2.250000 1.450980
# 2020-04-05 1.312500 1.725410 1.863636 1.831081
# 2020-04-12 1.428571 0.831354 1.016260 1.033210
# 2020-04-19 1.066667 0.817143 0.712000 0.942857
# 2020-04-26 0.906250 0.755245 0.617978 0.984848
# 2020-05-03 0.241379 0.486111 0.418182 0.461538
# 2020-05-10 0.285714 0.438095 0.231884 0.383333
# 2020-05-17 1.500000 0.478261 0.625000 0.326087
# 2020-05-24 1.333333 1.954545 1.600000 1.400000
# 2020-05-31 0.500000 2.069767 2.125000 1.047619
# 2020-06-07 2.500000 1.269663 0.500000 1.181818
# 2020-06-14 1.200000 1.566372 1.705882 1.076923
# 2020-06-21 1.666667 1.333333 2.241379 0.821429
# 2020-06-28 3.400000 1.949153 1.646154 2.217391
# 2020-07-05 2.323529 1.791304 1.785047 1.333333
# 2020-07-12 0.835443 1.220874 1.544503 1.720588
# 2020-07-19 1.181818 1.133201 1.403390 1.461538
# 2020-07-26 0.615385 0.855263 0.772947 0.783626
df_week_ratio['2020-05-03':'2020-07-25'].plot(grid=True)
Im Juli ist die wöchentliche Rate in jeder Altersgruppe gesunken.
Im Gegensatz zum Balkendiagramm werden beim Erstellen eines Liniendiagramms mit "plot ()" (oder "plot.line ()") die Datums- und Zeitdaten auf der X-Achse wie im obigen Beispiel entsprechend formatiert. Beachten Sie, dass es abhängig vom Inhalt der Datums- und Zeitdaten, wie später beschrieben, möglicherweise nicht formatiert wird.
Erstellen Sie eine Heatmap als weiteren Ansatz, um den Übergang der Anzahl neuer positiver Patienten nach Altersgruppen zu erfassen.
Hier wird die detaillierte Altersgruppe unverändert verwendet. Kreuztabelle mit pd.crosstab ()
wie im Beispiel des gestapelten Balkendiagramms. Da "resample ()" nicht verwendet wird, werden Datum und Uhrzeit "date_str" des Zeichenkettentyps angegeben. Die horizontale Achse wird mit "T" transponiert, um Datum und Uhrzeit einzustellen, und die untere Seite der vertikalen Achse wird mit "[:: -1]" transponiert, um die Reihenfolge der Zeilen nach der Translokation umzukehren.
df['age_detail'] = df['age_org'].replace(
{'Unter 10 Jahren': '0-9', '10er': '10-19', '20er Jahre': '20-29', '30er Jahre': '30-39', 'Vierziger Jahre': '40-49', '50er Jahre': '50-59',
'60er Jahre': '60-69', '70er Jahre': '70-79', '80er Jahre': '80-89', '90er Jahre': '90-', '100 Jahre und älter': '90-'}
)
df_ct_hm = pd.crosstab(df['date_str'], df['age_detail']).T[::-1]
Die Seaborn-Funktion "Heatmap ()" ist nützlich zum Erstellen von Heatmaps.
plt.figure(figsize=(15, 5))
sns.heatmap(df_ct_hm, cmap='hot')
Es kann bestätigt werden, dass sich die Infektion seit Juni allmählich auf ältere Menschen ausgeweitet hat.
Siehe unten für logarithmische Wärmekarten. Ich habe eine Warnung bekommen, aber es hat vorerst funktioniert.
Beachten Sie, dass, wenn die Daten "0" enthalten, ein Fehler auftritt, sodass der grobe Vorgang des Ersetzens von "0" durch "0,1" ausgeführt wird.
df_ct_hm_re = df_ct_hm.replace({0: 0.1})
min_value = df_ct_hm_re.values.min()
max_value = df_ct_hm_re.values.max()
log_norm = mpl.colors.LogNorm(vmin=min_value, vmax=max_value)
cbar_ticks = [math.pow(10, i) for i in range(math.floor(math.log10(min_value)),
1 + math.ceil(math.log10(max_value)))]
plt.figure(figsize=(15, 5))
sns.heatmap(df_ct_hm_re, norm=log_norm, cbar_kws={"ticks": cbar_ticks})
Übrigens habe ich die Idee der Visualisierung mit einer Heatmap anhand des Beispiels von Florida im folgenden Artikel gelernt.
@Zorinaq, der das Florida-Diagramm erstellt hat, hat den Code veröffentlicht, um zusätzlich zur Heatmap verschiedene Diagramme wie zukünftige Prognosen zu erstellen. Ohne Python-Kenntnisse scheint es schwierig zu sein, aber wenn Sie interessiert sind, sollten Sie einen Blick darauf werfen.
Wie aus dem oben gezeigten Ergebnis von "count ()" hervorgeht, gibt es 7186 Fälle, in denen die entladene Flagge in den öffentlichen Daten "1" ist, aber [New Coronavirus Infectious Disease Control Site in Tokio](https: / /stopcovid19.metro.tokyo.lg.jp/) "Entlassung usw. (einschließlich des Ablaufs der medizinischen Behandlungsdauer)" beträgt 9615 (Stand 31. Juli 2020, Aktualisierung 20:30).
Ich weiß nicht, ob sich die Reflexion der Daten nur verzögert oder aus irgendeinem Grund, aber bitte beachten Sie, dass die entladene Flagge der öffentlichen Daten von der aktuellen Situation abweichen kann.
Ähnlich wie beim Beispiel des Übergangs der Anzahl positiver Personen nach Altersgruppen wird der Übergang der entladenen Flagge in einem gestapelten Balkendiagramm angezeigt. Der fehlende Wert "NaN" wird als Vorverarbeitung durch "0" ersetzt.
print(df['discharged'].unique())
# [ 1. nan]
df['discharged'] = df['discharged'].fillna(0).astype('int')
print(df['discharged'].unique())
# [1 0]
print(pd.crosstab(df['date'], df['discharged']).resample('W', label='left').sum()[:-1].plot.bar(stacked=True))
Wenn Sie Bedenken haben, dass die Uhrzeit auf der X-Achse angezeigt wird, können Sie Datum und Uhrzeit des Index in eine Zeichenfolge konvertieren, wie im Beispiel für Änderungen der Anzahl der Positiven nach Altersgruppen. Ich lasse es hier. Gleiches gilt für die folgenden Beispiele.
Diese Grafik zeigt den Prozentsatz der entladenen Flags nach Veröffentlichungsdatum. Natürlich wurden viele der Personen, die lange Zeit als positiv bestätigt wurden (= das Datum der Veröffentlichung ist alt), entlassen (= die entlassene Flagge ist "1").
Nach Altersgruppe prüfen. Wenn Sie in pd.crosstab ()
mehrere Spalten in der Liste angeben, wird das Ergebnis als Multi-Index erhalten.
df_dc = pd.crosstab(df['date'], [df['age'], df['discharged']]).resample('W', label='left').sum()
print(df_dc)
# age 0-19 20-39 40-59 60-
# discharged 0 1 0 1 0 1 0 1
# date
# 2020-01-19 0 0 0 1 0 1 0 0
# 2020-01-26 0 0 0 1 0 0 0 0
# 2020-02-02 0 0 0 0 0 0 0 0
# 2020-02-09 0 0 0 2 0 5 0 9
# 2020-02-16 0 0 0 1 0 3 0 6
# 2020-02-23 0 0 0 2 0 3 0 5
# 2020-03-01 0 2 0 5 0 9 0 9
# 2020-03-08 0 0 0 5 0 10 1 10
# 2020-03-15 0 0 0 10 0 27 0 12
# 2020-03-22 0 7 0 100 0 88 2 100
# 2020-03-29 0 16 1 243 4 194 9 139
# 2020-04-05 0 21 5 416 1 368 11 260
# 2020-04-12 1 29 0 350 6 369 10 270
# 2020-04-19 2 30 3 283 6 261 17 247
# 2020-04-26 1 28 8 208 4 161 33 227
# 2020-05-03 1 6 6 99 5 64 23 97
# 2020-05-10 0 2 7 39 3 13 8 38
# 2020-05-17 2 1 10 12 2 8 9 6
# 2020-05-24 3 1 18 25 8 8 5 16
# 2020-05-31 0 2 13 76 8 26 9 13
# 2020-06-07 1 4 17 96 7 10 12 14
# 2020-06-14 3 3 84 93 13 16 17 11
# 2020-06-21 4 6 75 161 18 47 8 15
# 2020-06-28 4 30 37 423 19 88 20 31
# 2020-07-05 44 35 211 613 92 99 46 22
# 2020-07-12 62 4 803 203 250 45 113 4
# 2020-07-19 78 0 1140 0 414 0 171 0
# 2020-07-26 48 0 975 0 320 0 134 0
Die Grafiken von jungen und älteren Menschen sind wie folgt.
df_dc[:-1]['20-39'].plot.bar(stacked=True)
df_dc[:-1]['60-'].plot.bar(stacked=True)
Wie Sie sich vorstellen können, ist der Prozentsatz älterer Menschen, deren Entlassungsdatum nicht auf "1" festgelegt ist, höher, selbst wenn das Veröffentlichungsdatum älter ist, und es scheint, dass die Krankenhauseinweisung mit größerer Wahrscheinlichkeit verlängert wird.
Standardisieren, um das Verhältnis besser sichtbar zu machen.
x_young = df_dc[9:-1]['20-39']
x_young_norm = (x_young.T / x_young.sum(axis=1)).T
print(x_young_norm)
# discharged 0 1
# date
# 2020-03-22 0.000000 1.000000
# 2020-03-29 0.004098 0.995902
# 2020-04-05 0.011876 0.988124
# 2020-04-12 0.000000 1.000000
# 2020-04-19 0.010490 0.989510
# 2020-04-26 0.037037 0.962963
# 2020-05-03 0.057143 0.942857
# 2020-05-10 0.152174 0.847826
# 2020-05-17 0.454545 0.545455
# 2020-05-24 0.418605 0.581395
# 2020-05-31 0.146067 0.853933
# 2020-06-07 0.150442 0.849558
# 2020-06-14 0.474576 0.525424
# 2020-06-21 0.317797 0.682203
# 2020-06-28 0.080435 0.919565
# 2020-07-05 0.256068 0.743932
# 2020-07-12 0.798211 0.201789
# 2020-07-19 1.000000 0.000000
x_young_norm.plot.bar(stacked=True)
x_old = df_dc[9:-1]['60-']
x_old_norm = (x_old.T / x_old.sum(axis=1)).T
print(x_old_norm)
# discharged 0 1
# date
# 2020-03-22 0.019608 0.980392
# 2020-03-29 0.060811 0.939189
# 2020-04-05 0.040590 0.959410
# 2020-04-12 0.035714 0.964286
# 2020-04-19 0.064394 0.935606
# 2020-04-26 0.126923 0.873077
# 2020-05-03 0.191667 0.808333
# 2020-05-10 0.173913 0.826087
# 2020-05-17 0.600000 0.400000
# 2020-05-24 0.238095 0.761905
# 2020-05-31 0.409091 0.590909
# 2020-06-07 0.461538 0.538462
# 2020-06-14 0.607143 0.392857
# 2020-06-21 0.347826 0.652174
# 2020-06-28 0.392157 0.607843
# 2020-07-05 0.676471 0.323529
# 2020-07-12 0.965812 0.034188
# 2020-07-19 1.000000 0.000000
x_old_norm.plot.bar(stacked=True)
Die Prozentsätze von jungen und älteren Menschen, deren entlassene Flaggen nicht auf "1" gesetzt sind, sind unten angegeben. Schließlich werden ältere Menschen in der Regel für einen längeren Zeitraum ins Krankenhaus eingeliefert.
pd.DataFrame({'20-39': x_young_norm[0], '60-': x_old_norm[0]}).plot.bar()
Die Beispiele waren bisher mit dem plot ()
von DataFrame
und der Funktion seaborn relativ einfach zu handhaben, müssen jedoch in einigen Fällen von Matplotlib behandelt werden.
Nehmen Sie als Beispiel den Übergang der Gesamtzahl der neuen Positiven.
Hier wird value_counts ()
verwendet, um die Datums- und Zeitspalten zu zählen und die Gesamtzahl der neuen Positiven für jedes Veröffentlichungsdatum zu berechnen. Beachten Sie, dass wenn Sie nicht nach sort_index () sortieren, diese in absteigender Reihenfolge angeordnet werden.
s_total = df['date'].value_counts().sort_index()
print(s_total)
# 2020-01-24 1
# 2020-01-25 1
# 2020-01-30 1
# 2020-02-13 1
# 2020-02-14 2
# ...
# 2020-07-27 131
# 2020-07-28 266
# 2020-07-29 250
# 2020-07-30 367
# 2020-07-31 463
# Name: date, Length: 164, dtype: int64
print(type(s_total))
# <class 'pandas.core.series.Series'>
print(type(s_total.index))
# <class 'pandas.core.indexes.datetimes.DatetimeIndex'>
Im Gegensatz zu den vorherigen Beispielen handelt es sich um "Serie" anstelle von "DataFrame", aber die Idee ist in beiden Fällen dieselbe.
Wenn ein Balkendiagramm mit "plot.bar ()" erstellt wird, überlappen sich die X-Achsen wie unten gezeigt.
s_total.plot.bar()
In dem Beispiel im Vergleich zur Vorwoche habe ich geschrieben, dass beim Generieren eines Liniendiagramms mit plot ()
Datum und Uhrzeit entsprechend formatiert werden, in diesem Fall jedoch nicht.
s_total.plot()
Es scheint, dass der Grund, warum plot ()
nicht funktioniert, darin besteht, dass der Datums- und Zeitdatensatz im Index nicht periodisch ist (es tut mir leid, wenn es anders ist, weil ich es nicht im Detail untersucht habe).
Im Beispiel im Vergleich zur Vorwoche waren wöchentliche Daten ohne Auslassung vorhanden. In diesem Beispiel sind die Daten jedoch zu dem Zeitpunkt verfügbar, an dem die Anzahl der positiven Personen wie "2020-01-26" und "2020-01-27" "0" beträgt. Ist nicht vorhanden.
Fügen Sie mit "reindex ()" und "pd.date_range ()" Daten mit dem Wert "0" hinzu, auch an dem Datum und der Uhrzeit, an dem die Anzahl der Positiven "0" beträgt.
s_total_re = s_total.reindex(
index=pd.date_range(s_total.index[0], s_total.index[-1]),
fill_value=0
)
print(s_total_re)
# 2020-01-24 1
# 2020-01-25 1
# 2020-01-26 0
# 2020-01-27 0
# 2020-01-28 0
# ...
# 2020-07-27 131
# 2020-07-28 266
# 2020-07-29 250
# 2020-07-30 367
# 2020-07-31 463
# Freq: D, Name: date, Length: 190, dtype: int64
Dadurch werden Datum und Uhrzeit mit plot ()
entsprechend formatiert. Übrigens, wenn Sie die Protokollskalierung verwenden möchten, ist "logy = True".
s_total_re.plot()
s_total_re.plot(logy=True)
Auch in diesem Fall ist plot.bar ()
nutzlos.
s_total_re.plot.bar()
Für andere Typen als Liniendiagramme muss Matplotlib sie verarbeiten.
Stellen Sie Formatierer und Locator ein und generieren Sie ein Diagramm mit bar ()
von Matplotlib.
fig, ax = plt.subplots(figsize=(12, 4))
ax.xaxis.set_major_locator(mpl.dates.AutoDateLocator())
ax.xaxis.set_major_formatter(mpl.dates.DateFormatter('%Y-%m-%d'))
ax.xaxis.set_tick_params(rotation=90)
ax.bar(s_total.index, s_total)
Set_yscale ('log')
wenn Sie eine Protokollskala wünschen.
fig, ax = plt.subplots(figsize=(12, 4))
ax.xaxis.set_major_locator(mpl.dates.AutoDateLocator())
ax.xaxis.set_major_formatter(mpl.dates.DateFormatter('%Y-%m-%d'))
ax.xaxis.set_tick_params(rotation=90)
ax.set_yscale('log')
ax.bar(s_total.index, s_total)
Wenn Sie eine Linie mit gleitendem Durchschnitt hinzufügen möchten, verwenden Sie "rollend ()".
print(s_total.rolling(7).mean())
# 2020-01-24 NaN
# 2020-01-25 NaN
# 2020-01-30 NaN
# 2020-02-13 NaN
# 2020-02-14 NaN
# ...
# 2020-07-27 252.285714
# 2020-07-28 256.428571
# 2020-07-29 258.142857
# 2020-07-30 258.285714
# 2020-07-31 287.285714
# Name: date, Length: 164, dtype: float64
fig, ax = plt.subplots(figsize=(12, 4))
ax.xaxis.set_major_locator(mpl.dates.AutoDateLocator())
ax.xaxis.set_minor_locator(mpl.dates.DayLocator())
ax.xaxis.set_major_formatter(mpl.dates.DateFormatter('%Y-%m-%d'))
ax.xaxis.set_tick_params(labelsize=12)
ax.yaxis.set_tick_params(labelsize=12)
ax.grid(linestyle='--')
ax.margins(x=0)
ax.bar(s_total.index, s_total, width=1, color='#c0e0c0', edgecolor='black')
ax.plot(s_total.index, s_total.rolling(7).mean(), color='red')
Im obigen Beispiel wurden einige Einstellungen als Referenz hinzugefügt. margin (x = 0)
ist das Abschneiden des linken und rechten Randes. Sie können die Farbe anhand des Namens oder des Farbcodes angeben.
Die Daten, die für die Öffentlichkeit zugänglich sind, sind begrenzt, aber ich denke, dass Sie Ihr Verständnis vertiefen können, indem Sie selbst damit herumspielen. Bitte probieren Sie es aus.
Recommended Posts