[PYTHON] Visualisons l'état de l'infection par le virus corona avec Plotly [pour les débutants]

La prochaine fois https://qiita.com/Naoya_Study/items/851f4032fb6e2a5cd5ed

Avec la propagation de l'infection à coronavirus, diverses organisations ont publié des tableaux de bord sympas qui visualisent l'état de l'infection.

Exemple 1 Situation du nouveau coronavirus de l'OMS (COVID-19) WHO.PNG

Exemple 2 Ministère de la santé, du travail et du bien-être: cas national de nouvelle infection par le virus Corona korousho.PNG

Exemple 3 Toyo Keizai ONLINE New Corona Virus Domestic Infection Status toyokeizai.PNG

C'est cool! Je veux pouvoir faire quelque chose comme ça moi-même. Le but ultime est de créer un tableau de bord comme l'exemple ci-dessus à l'aide de Dataframe Dash spécifique à la visualisation de Python. Cette fois, je voudrais dessiner en utilisant la bibliothèque de visualisation Plotly comme préparation préliminaire. Veuillez me pardonner pour le désordre de code.

1. Données d'utilisation

Nous utiliserons les données sur l'état de l'infection publiées par Toyo Keizai Online au Japon. https://github.com/kaz-ogiwara/covid19/

import requests
import io
import pandas as pd
import re
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime as dt
url = 'https://raw.githubusercontent.com/kaz-ogiwara/covid19/master/data/individuals.csv'
res = requests.get(url).content
df = pd.read_csv(io.StringIO(res.decode('utf-8')), header=0, index_col=0)

Les données sont dans ce format.

Nouveau Non. Ancien Non. Année confirmée Mois confirmé Date fixe Âge sexe Lieu de résidence 1 Lieu de résidence 2
1 1 2020 1 15 30 s Homme Préfecture de Kanagawa
2 2 2020 1 24 Quarante Homme Chine (ville de Wuhan)
3 3 2020 1 25 30 s femme Chine (ville de Wuhan)
4 4 2020 1 26 Quarante Homme Chine (ville de Wuhan)
5 5 2020 1 28 Quarante Homme Chine (ville de Wuhan)
6 6 2020 1 28 Années 60 Homme Préfecture de Nara

Comme vous pouvez le voir, les données sur les personnes vivant en Chine sont également incluses, mais cette fois elles seront limitées au Japon, elles seront donc exclues.

def Get_Df():

    url = 'https://raw.githubusercontent.com/kaz-ogiwara/covid19/master/data/individuals.csv'
    res = requests.get(url).content
    df = pd.read_csv(io.StringIO(res.decode('utf-8')), header=0, index_col=0)

    pattern = r'Chine(...)'
    df['China'] = np.nan
    for i in range (1, len(df)+1):
        if re.match(pattern, df['Lieu de résidence 1'][i]):
            df['China'][i] = "T"
        else:
            df['China'][i] = "F"
    df = df[df["China"] != "T"].reset_index()
    
    return df
Index. Nouveau Non. Ancien Non. Année confirmée Mois confirmé Date fixe Âge sexe Lieu de résidence 1 Lieu de résidence 2 China
0 1 1 2020 1 15 30 s Homme Préfecture de Kanagawa NaN F
1 6 6 2020 1 28 Années 60 Homme Préfecture de Nara NaN F
2 8 8 2020 1 29 Quarante femme Préfecture d'Osaka NaN F
3 9 10 2020 1 30 Années 50 Homme Préfecture de Mie NaN F
4 11 12 2020 1 30 20 ans femme Kyoto NaN F

2. Nombre cumulé de personnes infectées par préfecture (graphique à barres horizontales)

def Graph_Pref():

    df = Get_Df()
    df_count_by_place = df.groupby('Lieu de résidence 1').count().sort_values('China')
    fig = px.bar(
        df_count_by_place,
        x="China",
        y=df_count_by_place.index,
        #En définissant l'orientation sur horizontal, il devient un graphique à barres horizontales.
        orientation='h',
        width=800,
        height=1000,
        )
    fig.update_layout(
        title="La préfecture où l'infection est signalée",
        xaxis_title="Nombre de personnes infectées",
        yaxis_title="",
     #Spécifiez simplement le modèle et ce sera un graphique basé sur le noir sans autorisation
        template="plotly_dark",
        )
    fig.show()

aaa.png

Plotly crée lui-même des diagrammes interactifs et à la mode.

3. Dessinez une carte à dispersion sur la carte

Ensuite, je voudrais tracer le nombre de personnes infectées par préfecture sur une carte du Japon sous forme de carte à dispersion. Pour ce faire, obtenez d'abord les informations de latitude et de longitude de la préfecture de chaque préfecture et combinez-les avec les données csv de Toyo Keizai Online. Localisation du bureau préfectoral Les données de latitude et de longitude utilisées provenaient de Everyone's Knowledge A little Convenient Book. Extrayez uniquement les données requises pour la latitude et la longitude et combinez-les à l'aide de pandas merge.

def Df_Merge():

    df = Get_Df()
    df_count_by_place = df.groupby('Lieu de résidence 1').count().sort_values('China')
    df_latlon = pd.read_excel("https://www.benricho.org/chimei/latlng_data.xls", header=4)
    df_latlon = df_latlon.drop(df_latlon.columns[[0,2,3,4,7]], axis=1).rename(columns={'Unnamed: 1': 'Lieu de résidence 1'})
    df_latlon = df_latlon.head(47)
    df_merge = pd.merge(df_count_by_place, df_latlon, on='Lieu de résidence 1')
    return df_merge
index Lieu de résidence 1 Nouveau Non. Ancien Non. Année confirmée Mois confirmé Date fixe Âge sexe Lieu de résidence 2 China latitude longitude
0 Préfecture de Gifu 1 1 1 1 1 1 1 0 1 35.39111 136.72222
1 Préfecture d'Ehime 1 1 1 1 1 1 1 0 1 33.84167 132.76611
2 Préfecture d'Hiroshima 1 1 1 1 1 1 1 0 1 34.39639 132.45944
3 Préfecture de Saga 1 1 1 1 1 1 1 0 1 33.24944 130.29889
4 Akita 1 1 1 1 1 1 1 0 1 39.71861 140.10250
5 Préfecture de Yamaguchi 1 1 1 1 1 1 1 0 1 34.18583 131.47139

Tracez sur la carte en utilisant le bloc de données ci-dessus.

def Graph_JapMap():
    df_merge = Df_Merge()
    df_merge['text'] = np.nan
    for i in range (len(df_merge)):
        df_merge['text'][i] = df_merge['Lieu de résidence 1'][i] + ' : ' + str(df_merge['China'][i]) + 'Homme'

    fig = go.Figure(data=go.Scattergeo(
        lat = df_merge["latitude"],
        lon = df_merge["longitude"],
        mode = 'markers',
        marker = dict(
                color = 'red',
                size = df_merge['China']/5+6,
                opacity = 0.8,
                reversescale = True,
                autocolorscale = False
                ),
        hovertext = df_merge['text'],
        hoverinfo="text",
    ))
    fig.update_layout(
        width=700,
        height=500,
        template="plotly_dark",
        title={
            'text': "Répartition des personnes infectées",
            'font':{
                'size':25
            },
            'y':0.9,
            'x':0.5,
            'xanchor': 'center',
            'yanchor': 'top'},
        margin = {
            'b':3,
            'l':3,
            'r':3,
            't':3
            },
        geo = dict(
            resolution = 50,
            landcolor = 'rgb(204, 204, 204)',
            coastlinewidth = 1,
            lataxis = dict(
                range = [28, 47],
            ),
            lonaxis = dict(
                range = [125, 150],
            ),
        )
    )
    fig.show()

map.png

Ceci est une image, mais si vous le faites en ligne, vous pouvez voir le nombre spécifique de personnes infectées en déplaçant le curseur sur le graphique, ce qui est cool. Essayez-le.

4. Modifications du nombre de personnes infectées (graphique à barres empilées)

Vient ensuite un graphique à barres de l'évolution du nombre de personnes infectées. Comme auparavant, transformez d'abord les données avec des pandas.

def Df_Count_by_Date():
    
    df = Get_Df()
    df['date'] = np.nan
    for i in range (len(df)):
        tstr = "2020-" + str(df['Mois confirmé'][i]) + "-" + str(df['Date fixe'][i])
        tdatetime = dt.strptime(tstr, '%Y-%m-%d')
        df['date'][i] = tdatetime

    df_count_by_date = df.groupby("date").count()

    df_count_by_date["total"] = np.nan
    df_count_by_date['gap'] = np.nan
    df_count_by_date["total"][0] = df_count_by_date["China"][0]
    df_count_by_date["gap"][0] = 0

    for i in range (1, len(df_count_by_date)):
        df_count_by_date["total"][i] = df_count_by_date['total'][i-1] + df_count_by_date['China'][i]
        df_count_by_date['gap'][i] = df_count_by_date['total'][i] - df_count_by_date['China'][i]
    df_count_by_date['total'] = df_count_by_date['total'].astype('int')
    df_count_by_date['gap'] = df_count_by_date['gap'].astype('int')

    return df_count_by_date
def Graph_total():

    df_count_by_date = Df_Count_by_Date()

    fig = go.Figure(data=[
        go.Bar(
            name='Nombre cumulé jusqu'à la veille',
            x=df_count_by_date.index,
            y=df_count_by_date['gap'],
            ),
        go.Bar(
            name='Nouveau numéro',
            x=df_count_by_date.index,
            y=df_count_by_date['China']
            )
    ])
    # Change the bar mode
    fig.update_layout(
        barmode='stack',
        template="plotly_dark",
        title={
            'text': "Changements dans le nombre de patients",
            'font':{
                'size':25
                },
            'y':0.9,
            'x':0.5,
            'xanchor': 'center',
            'yanchor': 'top'
            },
        xaxis_title="Date",
        yaxis_title="Nombre de personnes infectées",
        )
    fig.show()

total.png

5. Tracer sur la carte du monde

Le scattergeo de Plotly reconnaît le pays avec un code ISO à 3 chiffres, alors empruntez le code du pays sur le net et fusionnez-le avec les pandas.

INDEX COUNTRY Confirmed Deaths ISO CODES code size
0 China 81049 3230 CN / CHN CHN 82049.0
1 Italy 27980 2158 IT / ITA ITA 28980.0
2 Iran 14991 853 IR / IRN IRN 15991.0
3 South Korea 8236 75 KR / KOR KOR 9236.0
4 Spain 7948 342 ES / ESP ESP 8948.0
fig = px.scatter_geo(
        df_globe_merge,
        locations="code",
        color='Deaths',
        hover_name="COUNTRY",
        size="size",
        projection="natural earth"
        )
fig.update_layout(
        width=700,
        height=500,
        template="plotly_dark",
        title={
            'text': "Répartition des personnes infectées",
            'font':{
                'size':25
            },
            'y':0.9,
            'x':0.5,
            'xanchor': 'center',
            'yanchor': 'top'},
        geo = dict(
            resolution = 50,
            landcolor = 'rgb(204, 204, 204)',
            coastlinewidth = 1,
            ),
        margin = {
            'b':3,
            'l':3,
            'r':3,
            't':3
        })
fig.show()

world.png

Vous pouvez également le remplir.

fig = px.choropleth(
    df_globe_merge,
    locations="code",
    color='Confirmed',
    hover_name="COUNTRY",
    color_continuous_scale=px.colors.sequential.GnBu
    )
fig.update_layout(
        width=700,
        height=500,
        template="plotly_dark",
        title={
            'text': "Répartition des personnes infectées",
            'font':{
                'size':25
            },
            'y':0.9,
            'x':0.5,
            'xanchor': 'center',
            'yanchor': 'top'},
        geo = dict(
            resolution = 50,
            landcolor = 'rgb(204, 204, 204)',
            coastlinewidth = 0.1,
            ),
        margin = {
            'b':3,
            'l':3,
            'r':3,
            't':3
        }
    )
fig.show()

map2.png

L'échelle de couleur est Il change avec GnBU de color_continuous_scale = px.colors.sequential.GnBu. Liste de couleurs https://plot.ly/python/builtin-colorscales/

J'étais en train de réécrire pour Dash, mais cela ne fonctionnait pas bien s'il était visualisé avec plotly.express, donc j'ai également fait un dessin en utilisant plotly.graph_object.

fig = go.Figure(
    data=go.Choropleth(
        locations = df_globe_merge['code'],
        z = df_globe_merge['Confirmed'],
        text = df_globe_merge['COUNTRY'],
        colorscale = 'Plasma',
        marker_line_color='darkgray',
        marker_line_width=0.5,
        colorbar_title = 'Nombre de personnes infectées',
    )
)
fig.update_layout(
    template="plotly_dark",
    width=700,
    height=500,
    title={
        'text': "Répartition des personnes infectées",
        'font':{
             'size':25
            },
        'y':0.9,
        'x':0.5,
        'xanchor': 'center',
        'yanchor': 'top'},
    geo=dict(
        projection_type='equirectangular'
    )
)

fig.show()

map3.png

Cela a presque le même aspect, sauf que l'échelle de couleurs est changée de GnBu à Plasma.

Lorsque la transformation et la visualisation des données sont prêtes, j'aimerais les refléter dans Dash (la prochaine fois)

Recommended Posts

Visualisons l'état de l'infection par le virus corona avec Plotly [pour les débutants]
Créez une carte chronologique animée de l'état de l'infection par le virus corona avec python + plotly
INSÉRER dans MySQL avec Python [Pour les débutants]
[Python] Lire des images avec OpenCV (pour les débutants)
Création WebApi avec Python (création CRUD) Pour les débutants
[Pour les débutants] Essayez le web scraping avec Python
Les bases de Pandas pour les débutants ③ Créez un histogramme avec matplotlib
Raisonnement causal et recherche causale par Python (pour les débutants)
~ Conseils pour les débutants de Python donnés avec amour par Pythonista ① ~
~ Conseils pour les débutants de Python donnés avec amour par Pythonista ② ~
[Introduction pour les débutants] Manipuler MySQL avec Python
Visualisez plus clairement les prédictions de séries chronologiques de Prophet avec Plotly
[Pour les débutants] Script dans les 10 lignes (8. Carte graphique avec folium [2]
Visualisez le statut d'appréciation des œuvres d'art avec OpenCV
[Pour les débutants] Quantifier la similitude des phrases avec TF-IDF
Bases de Seaborn pour les débutants ③ Diagramme de dispersion (jointplot) * Avec histogramme