Chaque fois que j'ai vu le rapport sur le nombre de nouvelles infections à virus corona, je pensais "Je veux que vous m'en disiez plus sur la répartition par tranche d'âge", mais j'ai appris que Tokyo avait publié des données sur les patients positifs. ..
Ici, nous allons présenter comment analyser et visualiser les données publiées par le gouvernement métropolitain de Tokyo en utilisant Python et pandas, seaborn, Matplotlib.
Le point principal de cet article n'est pas les prédictions et les recommandations selon lesquelles «cela se produira dans le futur» et «ce genre de mesures devrait être prise», mais «cela facilite la visualisation des données, donc tout le monde devrait l'essayer». Si vous l'essayez vous-même, vous approfondirez votre compréhension, alors essayez-le.
Notez que si vous êtes particulier sur les détails tels que la disposition des graphiques et le format des axes, Matplotlib nécessitera un traitement fastidieux, donc je n'entrerai pas dans les détails ici (juste une petite touche à la fin). Plutôt que de créer un beau graphique pour une divulgation généralisée, l'objectif est de visualiser les données et de voir les tendances par vous-même.
Un exemple de code est également disponible sur GitHub. Le bloc-notes Jupyter (.ipynb
) est plus facile à lire, veuillez donc vous y référer également.
Les données positives des patients pour Tokyo sont publiées ci-dessous.
Vous pouvez y accéder à partir du lien «Obtenir des données ouvertes» du nouveau site de contrôle des infections par le virus corona de Tokyo.
En regardant History, il semble qu'il soit mis à jour de 10 à 15 heures en semaine.
Ci-dessous, une liste de sites qui ont bifurqué les sites de contre-mesures à Tokyo.
Certains sites, comme Tokyo, ont des liens vers des données ouvertes. Vous trouverez ci-dessous des exemples des préfectures de Hokkaido et Kanagawa.
Même s'il n'y a pas de lien sur le site, les données elles-mêmes doivent être publiées quelque part, vous pouvez donc les trouver en effectuant une recherche.
L'exemple de code suivant utilise des données de Tokyo. Les données d'autres préfectures peuvent avoir des éléments différents, mais le traitement de base est le même.
En outre, en tant que données liées au nouveau coronavirus, il existe des données agrégées telles que le nombre de tests PCR nationaux effectués, le nombre de positifs, le nombre de personnes hospitalisées et le nombre de décès annoncés par le ministère de la Santé, du Travail et du Bien-être social.
Les versions de chaque bibliothèque et de Python lui-même dans l'exemple de code ci-dessous sont les suivantes. Notez que différentes versions peuvent se comporter différemment.
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)]
Spécifiez le chemin vers le fichier CSV téléchargé dans pd.read_csv ()
et lisez-le comme DataFrame
. Les données jusqu'au 31 juillet 2020 sont utilisées à titre d'exemple.
df = pd.read_csv('data/130001_tokyo_covid19_patients_20200731.csv')
Vous pouvez spécifier l'URL directement dans l'argument de pd.read_csv ()
, mais il est plus sûr de le télécharger localement car il sera accédé plusieurs fois en vain au stade des essais et des erreurs.
# df = pd.read_csv('https://stopcovid19.metro.tokyo.lg.jp/data/130001_tokyo_covid19_patients.csv')
Le nombre de lignes / colonnes et les données au début et à la fin sont les suivants.
print(df.shape)
# (12691, 16)
print(df.head())
#No National Local Public Organization Code Prefecture Name City Ward Town / Village Name Published_Date de début_Date patient_Lieu de résidence Patient_Âge du patient_sexe\
#0 1 130001 Tokyo NaN 2020-01-24 ven NaN Wuhan City, Hubei Province Homme dans la quarantaine
#1 2 130001 Tokyo NaN 2020-01-25 Sat NaN Wuhan City, Province du Hubei Femmes dans la trentaine
#2 3 130001 Tokyo NaN 2020-01-30 Thu NaN Changsha City, Province du Hunan Femmes dans la trentaine
#3 4 130001 Tokyo NaN 2020-02-13 Thu NaN Male dans ses 70 ans à Tokyo
#4 5 130001 Tokyo NaN 2020-02-14 ven NaN Femmes dans la cinquantaine à Tokyo
#
#patient_Attribut patient_Condition patient_Patient symptôme_Indicateur d'historique de voyage Remarques Drapeau déchargé
# 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())
#No National Local Public Organization Code Prefecture Name City Ward Town / Village Name Published_Date de début_Date patient_Lieu de résidence Patient_Âge\
#12686 12532 130001 Tokyo NaN 2020-07-31 ven NaN NaN 70s
#12687 12558 130001 Tokyo NaN 2020-07-31 ven NaN NaN 70s
#12688 12563 130001 Tokyo NaN 2020-07-31 ven NaN NaN 70s
#12689 12144 130001 Tokyo NaN 2020-07-31 ven NaN NaN 80s
#12690 12517 130001 Tokyo NaN 2020-07-31 ven NaN NaN 80s
#
#patient_Patient de sexe_Attribut patient_Condition patient_Patient symptôme_Indicateur d'historique de voyage Remarques Drapeau déchargé
#12686 Mâle NaN NaN NaN NaN NaN NaN
#12687 Mâle NaN NaN NaN NaN NaN NaN
#12688 Mâle NaN NaN NaN NaN NaN NaN
#12689 Femelle NaN NaN NaN NaN NaN NaN
#12690 Male NaN NaN NaN NaN NaN NaN
Lorsque des données catégorielles telles que ces données sont les principales, il est facile d'obtenir une vue d'ensemble en utilisant des méthodes telles que count ()
, nunique ()
, ʻunique () et
value_counts () `.
count ()
renvoie le nombre d'éléments qui ne sont pas la valeur manquante NaN
. On peut constater que des informations détaillées telles que les noms, les symptômes et les attributs des villes / quartiers / villes / villages ne sont pas divulguées (pas de données), probablement en raison de la protection de la vie privée.
print(df.count())
# No 12691
#Code national de l'organisation publique locale 12691
#Nom de la préfecture 12691
#Nom de la ville 0
#Publié_Date 12691
#Vue 12691
#Début_Date 0
#patient_Lieu de résidence 12228
#patient_Âge 12691
#patient_Sexe 12691
#patient_Attribut 0
#patient_État 0
#patient_Symptôme 0
#patient_Indicateur d'historique de voyage 0
#Remarque 0
#Drapeau déchargé 7186
# dtype: int64
nunique ()
renvoie le nombre de types de données. Puisqu'il s'agit de données de Tokyo, le code du gouvernement local national et les noms de préfecture sont tous les mêmes.
print(df.nunique())
# No 12691
#Code national de l'organisation publique locale 1
#Nom de la préfecture 1
#Nom de la ville 0
#Publié_Date 164
#Jour 7
#Début_Date 0
#patient_Lieu de résidence 8
#patient_13 ans
#patient_Sexe 5
#patient_Attribut 0
#patient_État 0
#patient_Symptôme 0
#patient_Indicateur d'historique de voyage 0
#Remarque 0
#Drapeau déchargé 1
# dtype: int64
Pour chaque colonne (= Series
), vous pouvez vérifier les éléments uniques et leur nombre (fréquence d'occurrence) avec ʻunique ()et
value_counts ()`.
print(df['patient_résidence'].unique())
# ['Ville de Wuhan, province du Hubei' 'Ville de Changsha, province du Hunan' 'À Tokyo' 'Hors de la ville' '―' 'enquêter' '-' "'-" nan]
print(df['patient_résidence'].value_counts(dropna=False))
#Tokyo 11271
#En dehors de Tokyo 531
# NaN 463
# ― 336
#En cours d'enquête 85
#Ville de Wuhan, province du Hubei 2
#Ville de Changsha, province du Hunan 1
# '- 1
# - 1
# Name:patient_résidence, dtype: int64
print(df['patient_sexe'].unique())
# ['Masculin' 'Femme' "'-" '―' 'inconnue']
print(df['patient_sexe'].value_counts())
#Homme 7550
#Femme 5132
# '- 7
#Inconnu 1
# ― 1
# Name:patient_sexe, dtype: int64
Cette fois, nous limiterons la cible d'analyse à la date de publication, à l'âge du patient et à l'indicateur de sortie. Pour plus de commodité, changez le nom de la colonne avec rename ()
.
df = df[['Publié_Date', 'patient_Âge', 'Drapeau déchargé']].copy()
df.rename(columns={'Publié_Date': 'date_str', 'patient_Âge': 'age_org', 'Drapeau déchargé': 'discharged'},
inplace=True)
print(df)
# date_str age_org discharged
# 0 2020-01-24 années 40 1.0
# 1 2020-01-25 30 secondes 1.0
# 2 2020-01-30 30 s 1.0
# 3 2020-02-13 années 70 1.0
# 4 2020-02-14 50 1.0
# ... ... ... ...
# 12686 2020-07-31 années 70 NaN
# 12687 2020-07-31 années 70 NaN
# 12688 2020-07-31 années 70 NaN
# 12689 2020-07-31 années 80 NaN
# 12690 2020-07-31 années 80 NaN
#
# [12691 rows x 3 columns]
La raison d'utiliser copy ()
ici est d'empêcher SettingWithCopyWarning
. Dans ce cas, les données ne sont pas mises à jour, il n'y a donc aucun problème si vous les laissez seules.
En regardant la colonne de l'ère, elle contient des données telles que ʻinconnu et
'-`.
print(df['age_org'].unique())
# ['Quarante' '30 s' 'Années 70' 'Années 50' 'Années 60' 'Années 80' '20 ans' 'Moins de 10 ans' 'Années 90' '10 ans' '100 ans et plus'
# 'inconnue' "'-"]
print(df['age_org'].value_counts())
#Années 20 4166
#30 ans 2714
#Années 40 1741
#50 ans 1362
#Années 60 832
#Années 70 713
#Années 80 455
#Jeune 281
#Années 90 214
#Moins de 10 ans 200
#Inconnu 6
#100 ans et plus de 5
# '- 2
# Name: age_org, dtype: int64
Comme le nombre est petit, je vais l'exclure ici.
df = df[~df['age_org'].isin(['inconnue', "'-"])]
print(df)
# date_str age_org discharged
# 0 2020-01-24 années 40 1.0
# 1 2020-01-25 30 secondes 1.0
# 2 2020-01-30 30 s 1.0
# 3 2020-02-13 années 70 1.0
# 4 2020-02-14 50 1.0
# ... ... ... ...
# 12686 2020-07-31 années 70 NaN
# 12687 2020-07-31 années 70 NaN
# 12688 2020-07-31 années 70 NaN
# 12689 2020-07-31 années 80 NaN
# 12690 2020-07-31 années 80 NaN
#
# [12683 rows x 3 columns]
print(df['age_org'].unique())
# ['Quarante' '30 s' 'Années 70' 'Années 50' 'Années 60' 'Années 80' '20 ans' 'Moins de 10 ans' 'Années 90' '10 ans' '100 ans et plus']
Puisque la division d'âge est bonne, rendez-la un peu plus rugueuse. Tout le côté droit est entre parenthèses ()
car il se brise au milieu.
df['age'] = (
df['age_org'].replace(['Moins de 10 ans', '10 ans'], '0-19')
.replace(['20 ans', '30 s'], '20-39')
.replace(['Quarante', 'Années 50'], '40-59')
.replace(['Années 60', 'Années 70', 'Années 80', 'Années 90', '100 ans et plus'], '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
La colonne de date et d'heure (date de publication) date_str
est une chaîne de caractères. Pour un traitement ultérieur, ajoutez la colonne «date» convertie en type «datetime64 [ns]».
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
C'est la fin du prétraitement. De là, un exemple d'analyse et de visualisation des données est montré.
Ici, nous examinons l'évolution du nombre de nouveaux patients positifs par groupe d'âge. Le nombre total de nouveaux patients positifs sera décrit à la fin à titre d'exemple de traitement avec Matplotlib.
Utilisez pd.crosstab ()
pour croiser la date et l'heure (date de publication) et l'âge.
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'>
La colonne convertie au type datetime64 [ns]
devient un nouvel index et est traitée comme DatetimeIndex
. Notez que même si la sortie est la même, si vous spécifiez une date et une heure de type chaîne, ce ne sera pas DatetimeIndex
.
Agréger chaque semaine avec resample ()
. resample ()
ne peut être exécuté qu'avec DatetimeIndex
.
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
Visualisé avec plot ()
. Vous pouvez facilement créer un graphique à barres empilées.
df_ct_week[:-1].plot.bar(stacked=True)
Les données de la dernière ligne (la semaine dernière) sont exclues par «[: -1]». Ces données excluent la semaine dernière car elles n'incluent pas le samedi (1er août 2020) et ne sont pas appropriées pour être comparées aux autres semaines.
Le bloc-notes Jupyter affiche le graphique dans la cellule de sortie. Si vous voulez l'enregistrer en tant que fichier image, utilisez plt.savefig ()
. Vous pouvez également cliquer avec le bouton droit pour enregistrer la sortie du bloc-notes Jupyter.
plt.figure()
df_ct_week[:-1].plot.bar(stacked=True)
plt.savefig('image/bar_chart.png', bbox_inches='tight')
plt.close('all')
La condition d'occurrence est inconnue, mais il y a eu un problème lié à la coupure de l'étiquette de l'axe X lors de l'enregistrement. Reportez-vous à ce qui suit et définissez bbox_inches = 'tight'
pour résoudre le problème.
Si vous créez un graphique à barres tel qu'il est comme dans l'exemple ci-dessus, l'heure sera affichée sur l'étiquette de l'axe X. La solution la plus simple consiste à convertir l'index en une chaîne dans n'importe quel format.
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))
Normaliser l'ensemble et voir la transition du ratio d'âge. «T» est la translocation (permuter les lignes et les colonnes). Il peut être normalisé en le transposant, en le divisant par la valeur totale, en le transloquant à nouveau et en le ramenant à la valeur d'origine.
La plupart des jeunes (20-30 ans) ont fermé depuis juin, mais récemment, le pourcentage de personnes d'âge moyen (40 ans et plus) augmente.
df_ct_week_str_norm = (df_ct_week_str.T / df_ct_week_str.sum(axis=1)).T
Les changements entre les jeunes (20-30 ans) et les personnes âgées (60 ans et plus) sont les suivants. Le nombre absolu de personnes âgées a également augmenté pour atteindre le niveau de fin mars.
df_ct_week_str[:-1][['20-39', '60-']].plot.bar(figsize=(8, 4))
Pour voir l'élan de la propagation de l'infection, calculez le changement par rapport à la semaine précédente.
Les données peuvent être décalées et divisées par shift ()
.
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)
En juillet, le taux hebdomadaire a diminué dans chaque groupe d'âge.
De plus, contrairement au graphique à barres, lors de la création d'un graphique linéaire avec plot ()
(ou plot.line ()
), les données de date et d'heure sur l'axe X sont formatées de manière appropriée comme dans l'exemple ci-dessus. Notez qu'il peut ne pas être formaté en fonction du contenu des données de date et d'heure comme décrit plus loin.
Créer une carte thermique comme autre approche pour saisir la transition du nombre de nouveaux patients positifs par groupe d'âge.
Ici, le groupe d'âge détaillé est utilisé tel quel. Tableau croisé avec pd.crosstab ()
comme dans l'exemple du graphique à barres empilées. Puisque resample ()
n'est pas utilisé, la date et l'heure date_str
du type chaîne de caractères sont spécifiées. L'axe horizontal est transposé avec «T» pour régler la date et l'heure, et le côté inférieur de l'axe vertical est transposé avec «[:: -1]» pour inverser la disposition des lignes après translocation.
df['age_detail'] = df['age_org'].replace(
{'Moins de 10 ans': '0-9', '10 ans': '10-19', '20 ans': '20-29', '30 s': '30-39', 'Quarante': '40-49', 'Années 50': '50-59',
'Années 60': '60-69', 'Années 70': '70-79', 'Années 80': '80-89', 'Années 90': '90-', '100 ans et plus': '90-'}
)
df_ct_hm = pd.crosstab(df['date_str'], df['age_detail']).T[::-1]
La fonction seaborn heatmap ()
est utile pour créer des heatmaps.
plt.figure(figsize=(15, 5))
sns.heatmap(df_ct_hm, cmap='hot')
On peut confirmer que l'infection s'est progressivement propagée aux personnes âgées depuis juin.
Voir ci-dessous pour les cartes thermiques à l'échelle logarithmique. J'ai reçu un avertissement, mais cela a fonctionné pour le moment.
Notez que s'il y a «0» dans les données, une erreur se produira, donc le processus approximatif de remplacement de «0» par «0,1» est effectué.
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})
Au fait, j'ai appris l'idée de visualiser avec une carte thermique en regardant l'exemple de la Floride dans l'article suivant.
@Zorinaq, qui a créé le graphique de Floride, a publié le code pour créer divers graphiques tels que les prévisions futures en plus de la carte thermique. Cela semble difficile sans une certaine connaissance de Python, mais si vous êtes intéressé, vous voudrez peut-être jeter un coup d'œil.
Comme le montre le résultat de count ()
ci-dessus, il y a 7186 cas où l'indicateur déchargé est "1" dans les données publiques, mais [Nouveau site de contrôle des maladies infectieuses du coronavirus à Tokyo](https: / /stopcovid19.metro.tokyo.lg.jp/) "Décharge, etc. (y compris la fin de la période de traitement médical)" est 9615 (mise à jour à 20h30 le 31 juillet 2020).
Je ne sais pas si la réflexion des données est simplement retardée ou pour une raison quelconque, mais veuillez noter que le drapeau déchargé des données publiques peut être différent de la situation actuelle.
Similaire à l'exemple de la transition du nombre de personnes positives par tranche d'âge, la transition du drapeau déchargé est visualisée dans un graphique à barres empilées. La valeur manquante «NaN» est remplacée par «0» en tant que prétraitement.
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))
Si vous êtes préoccupé par l'heure affichée sur l'axe X, vous pouvez convertir la date et l'heure de l'index en une chaîne de caractères, comme dans l'exemple des changements du nombre de positifs par tranche d'âge. Je le laisse ici. Il en va de même pour les exemples suivants.
Ce graphique montre le pourcentage de drapeaux déchargés par date de publication. Bien sûr, la plupart des personnes qui ont été confirmées positives pendant une longue période (= la date de publication est ancienne) ont été libérées (= le drapeau déchargé est «1»).
Vérifiez par tranche d'âge. Dans pd.crosstab ()
, si vous spécifiez plusieurs colonnes dans la liste, le résultat sera obtenu sous la forme d'un multi-index.
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
Les graphiques des jeunes et des personnes âgées sont les suivants.
df_dc[:-1]['20-39'].plot.bar(stacked=True)
df_dc[:-1]['60-'].plot.bar(stacked=True)
Comme vous pouvez l'imaginer, le pourcentage de personnes âgées dont la date de sortie n'est pas fixée à «1» est plus élevé même si la date de publication est plus ancienne, et il semble que l'hospitalisation soit plus susceptible d'être prolongée.
Standardisez pour rendre le rapport plus facile à voir.
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)
Les pourcentages de jeunes et de personnes âgées dont les drapeaux déchargés ne sont pas réglés sur «1» sont indiqués ci-dessous. Après tout, les personnes âgées ont tendance à rester à l'hôpital plus longtemps.
pd.DataFrame({'20-39': x_young_norm[0], '60-': x_old_norm[0]}).plot.bar()
Les exemples jusqu'à présent ont été relativement faciles à gérer en utilisant le plot ()
de DataFrame
et la fonction seaborn, mais dans certains cas, ils doivent être gérés par Matplotlib.
Prenons l'exemple de la transition du nombre total de nouveaux positifs.
Ici, value_counts ()
est utilisé pour compter les colonnes de date et d'heure et calculer le nombre total de nouveaux positifs pour chaque date de publication. Notez que si vous ne triez pas par sort_index ()
, ils seront classés par ordre décroissant.
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'>
Contrairement aux exemples précédents, il s'agit de «Series» au lieu de «DataFrame», mais l'idée est la même dans les deux cas.
Lorsqu'un graphique à barres est généré avec plot.bar ()
, les axes X se chevauchent comme indiqué ci-dessous.
s_total.plot.bar()
Dans l'exemple de la semaine précédente, j'ai écrit que si vous utilisez plot ()
pour générer un graphique linéaire, cela formatera la date et l'heure de manière appropriée, mais cela ne fonctionnera pas.
s_total.plot()
Il semble que la raison pour laquelle plot ()
ne fonctionne pas est que les données de date et d'heure dans l'index ne sont pas périodiques (je suis désolé si c'est différent car je ne l'ai pas étudié en détail).
Dans l'exemple par rapport à la semaine précédente, les données hebdomadaires existaient sans omission, mais dans cet exemple, les données sont disponibles à la date et à l'heure où le nombre de personnes positives telles que «2020-01-26» et «2020-01-27» est «0». N'existe pas.
En utilisant reindex ()
et pd.date_range ()
, ajoutez des données avec la valeur "0" même à la date et à l'heure où le nombre de positifs est "0".
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
Cela formatera la date et l'heure de manière appropriée avec plot ()
. Au fait, si vous souhaitez utiliser l'échelle logarithmique, logy = True
.
s_total_re.plot()
s_total_re.plot(logy=True)
Même dans ce cas, plot.bar ()
est inutile.
s_total_re.plot.bar()
Pour les types autres que les graphiques linéaires, Matplotlib doit les gérer.
Définissez Formatter et Locator, et générez un graphique avec bar ()
de 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')
si vous voulez une échelle log.
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)
Si vous voulez ajouter une ligne moyenne mobile, utilisez rolling ()
.
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')
Dans l'exemple ci-dessus, certains paramètres ont été ajoutés pour référence. margins (x = 0)
est la troncature des marges gauche et droite. Vous pouvez spécifier la couleur par nom ou code couleur.
Les données ouvertes au public sont limitées, mais je pense que vous pouvez approfondir votre compréhension en jouant avec vous-même. Veuillez l'essayer.
Recommended Posts