Python {Article013}

ようこそ「Python」へ...

厚労省のサイトからCOVID-19のデータをダウンロードしてPandas+Matplotlibで解析するには【Python】

ここでは「厚労省」のサイトから COVID-19(新型コロナ)の最新データをダウンロードしてPython, Pandas, Matplotlibで解析する方法を説明します。 厚労省のサイトからCSVファイルをダウンロードするにはPandasのread_csv()メソッドを使用します。 ここではread_csv()の引数に直接CSVファイルの「URL」を指定して取り込みます。なので完全に自動化できます。

ここではVisula Studio Code(VSC)の「Python Interactive window」 を使用してJupter(IPython Notebook)のような環境で説明します。 VSCを通常の環境からインタラクティブな環境に切り換えるにはコードを記述するときコメント「# %%」を入力します。 詳しい、操作手順については「ここ」 を参照してください。 インタラクティブな環境では、Pythonの「print(), plt.show()」などを使う必要がないので掲載しているコードでは省略しています。 VSCで通常の環境で使用するときは、必要に応じて「print(), plt.show()」等を追加してください。

この記事では、Pandas、Matplotlibのライブラリを使用しますので 「記事(Article001) | 記事(Article002) | 記事(Article003) | 記事(Article004)」 を参照して事前にインストールしておいてください。 Pythonのコードを入力するときにMicrosoftのVisula Studio Codeを使用します。 まだ、インストールしていないときは「記事(Article001)」を参照してインストールしておいてください。

説明文の左側に図の画像が表示されていますが縮小されています。 画像を拡大するにはマウスを画像上に移動してクリックします。 画像が拡大表示されます。拡大された画像を閉じるには右上の[X]をクリックします。 画像の任意の場所をクリックして閉じることもできます。

click image to zoom!
発症者数
click image to zoom!
重症者数
click image to zoom!
死亡者累計

厚労省のサイトからCOVID-19のCSVファイルを取り込んでクリーンナップする

  1. 厚労省のサイトからCSVファイルを取り込む

    Visual Studio Codeを起動したら以下のコードを入力して実行します。 行23-33ではPandasのread_csv()メソッドを使用して厚労省のサイトから直接COVID-19の各種データを取り込んでいます。 read_csv()の引数にCSVファイルの「URL」を指定するとファイルを手動でダウンロードせずに取り込むことができます。 行35-36では都道府県の県庁所在地の「緯度経度」が格納されているCSVファイルをローカルディスクから取り込んでいます。 都道府県別の緯度経度のデータは 「国土交通省」のサイトからダウンロードできます。 CSVファイルは図1のようなレイアウトで作成してください。列「prefucture」は日本語ではなくローマ字で入力します。 ちなみに厚労省のCOVID-19のデータも都道府県名は「ローマ字」になっています。 右側のインタラクティブ・ウィンドウに「raw1.info()」を入力して[Shift+Enter]で実行してみてください。
    # Data Source: https://www.mhlw.go.jp/stf/covid-19/open-data.html
    # csv files: 
    # newly_confirmed_cases_daily.csv 
    # requiring_inpatient_care_etc_daily.csv
    # deaths_cumulative_daily.csv 
    # severe_cases_daily.csv 
    # pcr_tested_daily.csv 
    # latlng_data_center.csv 
    # %%
    
    # Marge COVID-19 Data Files
    
    # Import the necessary libraries  
    import pandas as pd
    #from pandas.core.frame import DataFrame
    #import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import numpy as np
    
    # %%
    # 1) Load the csv files 
    csv1 = 'https://covid19.mhlw.go.jp/public/opendata/newly_confirmed_cases_daily.csv'
    raw1 = pd.read_csv(csv1)
    
    csv2 = 'https://www.mhlw.go.jp/content/pcr_tested_daily.csv   # Exclude Prefecture (ken)
    raw2 = pd.read_csv(csv2)
    
    csv3 = 'https://covid19.mhlw.go.jp/public/opendata/deaths_cumulative_daily.csv'
    raw3 = pd.read_csv(csv3)
    
    csv4 = 'https://covid19.mhlw.go.jp/public/opendata/severe_cases_daily.csv'
    raw4 = pd.read_csv(csv4)
    
    csv5 = 'data/csv/covid-19/japan/latlng_data_center.csv'
    raw5 = pd.read_csv(csv5)
    click image to zoom!
    図1-1
    図1-1はインタラクティブ・ウィンドウから「raw1.info()」と「raw5.head(3)」を入力して実行した結果です。
    click image to zoom!
    図1-2
    図1-2は厚労省のサイトで公開されているCOVID-19のCSVファイルのレイアウトです。 緯度経度のCSVファイル「latlng_data_center.csv」は国土交通省からダウンロードしたものを編集しています。
  2. CSVファイルの列名を変更する

    厚労省のCSVファイルの列名はローマ字と日本語が混在しています。 ここではすべてのCSVファイルの列名をローマ字に統一します。 行2-5ではDataFrameのset_axis()メソッドで各種CSVファイルの列名をローマ字に変更しています。 列名を変更するときは引数「axis=1」を指定します。 さらに、変更した内容をDataFrameに反映させるために「inplace=True」も指定します。 行8-11ではPandasのto_datetime()メソッドで列「date」をstr型からdatetime型に変換しています。 行12-18では各DataFrameに列「file_id」を追加してファイルのIDを設定しています。 この列は一元化したファイルを取り込んだときに、どのCSVファイルに属するデータかを識別するために使用します。
    # Rename Column names
    raw1.set_axis(['date', 'prefecture', 'new_cases'], axis=1, inplace=True)
    raw2.set_axis(['date', 'new_tests'], axis=1, inplace=True)
    raw3.set_axis(['date', 'prefecture','total_deaths'], axis=1, inplace=True)
    raw4.set_axis(['date', 'prefecture','severe_cases'], axis=1, inplace=True)
    
    # Convert str to datetime
    raw1['date'] = pd.to_datetime(raw1['date'])
    raw2['date'] = pd.to_datetime(raw2['date'])
    raw3['date'] = pd.to_datetime(raw3['date'])
    raw4['date'] = pd.to_datetime(raw4['date'])
    
    # Add a file id
    raw1['file_id'] = 'new_cases'
    raw2['file_id'] = 'new_tests'
    raw3['file_id'] = 'tot_deaths'
    raw4['file_id'] = 'new_severe_cases'
    raw5['file_id'] = 'latlng_data'
    click image to zoom!
    図2
    図2はインタラクティブ・ウィンドウから「raw1.info()」と「raw2.info()」を入力して実行した結果です。 DataFrameの列名が変更されているのが確認できます。
  3. CSVファイルに日別・累計の列を追加する

    行3-12では新規感染者のCSVファイルを処理しています。 行3ではDataFrameのunique()メソッドでユニークな都道府県名を取得しています。 さらにtolist()メソッドでそれをリスト型で返しています。 変数「prefs」には都道府県名がリスト型で格納されます。 行4ではPythonの「del」で変数prefsから都道府県名が「ALL」の要素を削除しています。 行5-9のforループでは変数dfxのDataFrameに格納されている感染者のデータを都道府県別に絞り込んで日別の累計感染者数を計算して新規列「total_cases」に格納しています。 日別の感染者数から日別の累計感染者数を計算するにはDataFrameのcumsum()メソッドを使用します。 「dfx['new_cases'].cumsum() 」のように記述するとDataFrameの列「new_cases(日別感染者数)」から累計感染者数を自動的に計算してくれます。 行10-12のforループでは変数raw1のDataFrameに新規列「total_cases」を追加して日別の累計感染者数(dfxのDataFrameから取得)を格納しています。 DataFrameに新規列「total_cases」を追加して値を格納するにはDataFrameのloc()メソッドを使用します。 loc()の引数1には更新するレコードを特定するための条件を指定します。 ここでは都道府県名「prefecture」と日付「date」が一致するレコードを探して更新するようにしています。 引数2には更新する列名「total_cases」と値を指定します。

    行14-23では重症者のCSVファイルを処理しています。 ここでは日別重症者数「severe_cases」から日別累計重症者数を計算して新規列「total_severe_cases」に格納しています。 日別重症者数から日別累計重症者数を計算するにはDataFrameのcumsum()メソッドを使用します。 具体的には「 dfx['severe_cases'].cumsum()」のように記述します。

    行26-35では死亡者のCSVファイルを処理しています。 ここでは日別累計死亡者数から日別死亡者数を計算して新規列「new_deaths」に格納しています。 日別累計死亡者数から日別死亡者数を計算するにはDataFrameのdiff()メソッドを使用します。 具体的には「dfx['total_deaths'].diff()」のように記述します。
    # 4) Add daily or total fields
    # 4-1) raw1 newly_confirmed_cases_daily.csv : add a total_cases field
    prefs = raw1['prefecture'].unique().tolist()
    del prefs[0]    # Remove 'ALL' from the list
    for pref in prefs:
        filter_by = (raw1['prefecture'] == pref) 
        dfx = raw1[filter_by]
        dfx.sort_values(by=['date'], inplace=True)
        dfx['total_cases'] = dfx['new_cases'].cumsum()  
        for index, row in dfx.iterrows():
            filter_by = (raw1['prefecture'] == row.prefecture) & (raw1['date'] == row.date)
            raw1.loc[filter_by, 'total_cases'] = row.total_cases
    # 4-2) raw4 severe_cases_daily.csv : add a total_severe_cases field
    prefs = raw4['prefecture'].unique().tolist()
    del prefs[0]    # Remove 'ALL' from the list
    for pref in prefs:
        filter_by = (raw4['prefecture'] == pref) 
        dfx = raw4[filter_by]
        dfx.sort_values(by=['date'], inplace=True)
        dfx['total_severe_cases'] = dfx['severe_cases'].cumsum()  
        for index, row in dfx.iterrows():
            filter_by = (raw4['prefecture'] == row.prefecture) & (raw4['date'] == row.date)
            raw4.loc[filter_by, 'total_severe_cases'] = row.total_severe_cases
    
    # 4-3) raw3 deaths_cumulative_daily.csv : add a new_deahts filed
    prefs = raw3['prefecture'].unique().tolist()
    del prefs[0]    # Remove 'ALL' from the list
    for pref in prefs:
        filter_by = (raw3['prefecture'] == pref)
        dfx = raw3[filter_by]
        dfx.sort_values(by=['date'], inplace=True)
        dfx['new_deaths'] = dfx['total_deaths'].diff() 
        for index, row in dfx.iterrows():
            filter_by = (raw3['prefecture'] == row.prefecture) & (raw3['date'] == row.date)
            raw3.loc[filter_by, 'new_deaths'] = row.new_deaths
  4. 複数のCSVファイルをマージして一元化する

    行2-5ではpandasのconcat()メソッドを使用して複数のDataFrameを1個のDataFrameにまとめて一元化しています。 concat()でDataFrameをマージするとき異なる列名が存在する場合列名が自動的に追加されます。 concat()の引数に「ignore_index=True」を指定してindexが複数作成されないようにします。 レコード(行)をマージするときは引数「axis=0」を指定します。
    # Merge the CSV files
    raw = pd.concat([raw1, raw2], ignore_index=True, axis=0)
    raw = pd.concat([raw, raw3], ignore_index=True, axis=0)
    raw = pd.concat([raw, raw4], ignore_index=True, axis=0)
    raw = pd.concat([raw, raw5], ignore_index=True, axis=0)
    click image to zoom!
    図3
    図3は「raw.info()」と「raw.head(2)」を入力して実行した結果です。 すべてのDataFrameのレコードがマージされているのが確認できます。
  5. COVID-19のデータをクリーンナップする

    行3-12ではDataFrameのfillna()メソッドを使用して不正なデータをクリーンナップしています。 列「date」が空のときは「2019/1/1」と置換します。 列「prefecture」が空のときは「N/A」と置換します。 列「new_cases, new_tests, total_deaths, severe_cases, lan, long」がNaN(Not a Number)なら「0」と置換します。 行12-18では列「prefecture」の値が「ALL」のレコード(行)を削除しています。 ちなみに都道府県名に「ALL」が格納されているときは全国の統計データであることを意味します。
    # To replace all NaN values with 2019/1/1, N/A, 0
    
    replace_values = {
        'date':'2019/1/1',
        'prefecture': 'N/A',
        'new_cases': 0, 
        'new_tests': 0, 
        'total_deaths': 0, 
        'severe_cases': 0,  
        'lan': 0, 'long': 0
        }
    raw.fillna(value=replace_values, inplace=True)
    raw.isnull().sum().sum()
    
    # Drop rows if the prefecture == 'ALL'
    
    index_no = raw[ raw['prefecture'] == 'ALL' ].index 
    raw.drop(index_no, inplace=True)
    raw.head()
    click image to zoom!
    図4
    図4は「raw.head()」の実行結果です。 DataFrameのデータがクリーンナップされていることが確認できます。
  6. すべてのデータに「緯度経度」を埋め込んで保存する

    行2ではDataFrameのset_index()メソッドで列「prefecture」にindexを設定しています。 raw5のDataFrameには都道府県の県庁所在地の経度緯度が格納されています。 行3-4のforループではrawのDataFrameの列「lan, long」に都道府県の緯度経度を格納しています。 rawのDataFrameにはCOVID-19のすべてのデータが一元化されて格納されています。 行5ではDataFrameのreset_index()メソッドでraw5のindexをデフォルトに戻しています。 これで列「prefecture」は通常の列になります。 行6-7ではDataFrameのto_csv()メソッドでDataFrame(raw)のデータをCSVファイルに保存しています。 to_csv()の引数1にはCSVファイルのパスを指定しています。 引数2には「index=False」を指定してデフォルトのindexを保存しないようにしています。
    # Update all lan, long if value is 0
    raw5.set_index('prefecture', inplace=True)
    for index, row in raw5.iterrows():
        raw.loc[ raw['prefecture'] == index, ['lan', 'long'] ] = [row.lan, row.long] 
    raw5.reset_index(inplace=True)
    csv_file = 'data/csv/covid-19/japan/combined.csv'
    raw.to_csv(csv_file, index=False)
    click image to zoom!
    図5
    図5はインタラクティブ・ウィンドウから「raw.head(5)」を実行させた結果です。 DataFrame(raw)の列「lan, long」に緯度経度が格納されているのが確認できます。

一元化したCOVID-19のデータを解析する

  1. 一元化したCOVID-19のデータを取り込む

    行10-12では一元化されたCOVID-19のCSVデータを取り込んでいます。 行11ではPandasのread_csv()メソッドでCSVファイルを取り込んでDataFrameに格納しています。 行15ではstr型の列「date」をdatetime型に変換しています。
    # Import the necessary libraries  
    import pandas as pd
    #from pandas.core.frame import DataFrame
    #import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import numpy as np
    
    # 1) Load the csv file cases 
    csv_file = 'data/csv/covid-19/japan/combined.csv'
    raw = pd.read_csv(csv_file) 
    df = raw
    
    # Convert str to datetime
    df['date'] = pd.to_datetime(df['date'])
    click image to zoom!
    図6
    図6はインタラクティブ・ウィンドウから「df.head(3)」と「df.tail(3)」を入力して実行させた結果です。 DataFrameの先頭と終端から3レコードずつ表示させています。
  2. 発症者数の多い都道府県(5県)の円グラフを作成する

    行2ではmatplotlibが日本語にも対応できるように日本語のフォントを設定しています。 行5ではDataFrameのgroupby()メソッドで列「prefecture」をグループ化しています。 さらにsum()メソッドで列「new_cases」の合計値を計算させています。 列「new_cases」には日別の新規発症者数が格納されています。 最後にsort_values()メソッドで発症者数の合計値を降順に並べ替えています。 これで変数「desc_prefs」には発症者数の多い順に「都道府県名、新規発症者数」のSeriesが格納されます。 SeriesとはDataFrameの特定の列の全行のことです。 行12-18のforループでは発症者数上位5県の県名と人数を変数「label, values」に格納しています。 上位5県以外の県は変数「other_total」に集計します。 行19-20では上位5県以外の「その他」の県を変数「labels, values」に追加しています。 行22-25ではグラフの円の線、クサビの部分の境界線などの色と線の幅を設定しています。 行26では4番目の県を円グラフから離して目立つようにしています。 ちなみに4番目の埼玉県は著者の住んでいるところです。 行27では図のサイズを設定しています。 行29-35ではmatplotlibのpie()メソッドで円グラフを作成しています。 行37では円グラフのタイトルを設定しています。 行40-45では円グラフの凡例を設定しています。
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Yu Gothic'  # Meiryo, Yu Gothic
    # 1) Draw a pie chart for new_cases
    # Get to see which prefectures have the most cases currently
    desc_prefs = df.groupby('prefecture')['new_cases'].sum().sort_values(ascending=False)	
    desc_prefs
    # Generate lables and values for the pie chart
    labels = []
    values = []
    pref_count = 5   
    other_total = 0
    for pref in desc_prefs.index:
        if pref_count > 0:
            labels.append(pref)
            values.append(desc_prefs[pref])
            pref_count -= 1
        else:
            other_total += desc_prefs[pref]
    labels.append("Other")
    values.append(other_total)
    # Draw a pie cahrt
    wedge_dict = {
        'edgecolor': 'black',
        'linewidth': 2        
    }
    explode = (0, 0, 0, 0.1, 0, 0)  
    plt.figure(figsize=(10,8))
    
    plt.pie(
        values, 
        labels=labels, 
        explode=explode, 
        autopct='%1.1f%%', 
        textprops={'color':'w'},
        wedgeprops=wedge_dict)
    
    plt.title('COVID-19 Cases\n(発症者数)', color='w', fontsize=18)
    #plt.legend(fontsize=15, loc='center right')
    
    plt.legend(
        fontsize=16,
        labels=['東京','大阪','神奈川','埼玉','愛知','その他'] ,   
        loc='center right',
        bbox_to_anchor=(1, 0, 0.5, 1)
        )
    click image to zoom!
    図7-1
    図7-1は実行結果です。新規発症者数の上位5県の円グラフが表示されています。 上位から順番に東京(22.3%)、大阪(11.6%)、神奈川(9.9%)、埼玉(6.8%)、愛知(6.1%)の順になっています。
    click image to zoom!
    図7-2
    図7-2はインタラクティブ・ウィンドウから「desc_prefs」を入力して実行した結果です。 列「prefecture」と列「new_cases」のSeriesが表示されています。
    click image to zoom!
    図7-3
    図7-3はインタラクティブ・ウィンドウから「desc_prefs.index」を入力して実行した結果です。 都道府県名が新規発症者数の多い順に表示されています。
  3. 重症者数の多い都道府県(5県)の円グラフを作成する

    ここではDataFrameの列「severe_cases」に格納されている重症者数を都道府県別に集計して上位5県の円グラフを作成しています。
    # 2) Draw a pie chart for severe_cases
    # Get to see which prefectures have the most severe cases currently
    desc_prefs = df.groupby('prefecture')['severe_cases'].sum().sort_values(ascending=False)	
    desc_prefs
    
    # Generate lables and values for the pie chart
    labels = []
    values = []
    pref_count = 5  
    other_total = 0
    for pref in desc_prefs.index:
        if pref_count > 0:
            labels.append(pref)
            values.append(desc_prefs[pref])
            pref_count -= 1
        else:
            other_total += desc_prefs[pref]
    labels.append("Other")
    values.append(other_total)
    # Draw a pie cahrt
    wedge_dict = {
        'edgecolor': 'black',
        'linewidth': 2        
    }
    explode = (0, 0, 0, 0, 0.1, 0) 
    plt.figure(figsize=(10,8))
    plt.pie(
        values, 
        labels=labels, 
        explode=explode, 
        autopct='%1.1f%%', 
        textprops={'color':'w'},
        wedgeprops=wedge_dict)
    
    plt.title('COVID-19 Severe Cases\n(重症者数)', color='w', fontsize=18)
    
    plt.legend(
        fontsize=16,
        labels=['大阪','東京','神奈川','兵庫','埼玉','その他'] ,   
        loc='center right',
        bbox_to_anchor=(1, 0, 0.5, 1)
        )
    click image to zoom!
    図8
    図8は実行結果です。 重症者数は多い順に大阪(26.3%), 東京(11.8%), 神奈川(9.1%), 兵庫6.4%), 埼玉(6.2%)になっています。
  4. 死亡者数の多い都道府県(7県)の円グラフを作成する

    ここではDataFrameの列「total_deaths」に格納されている死亡者数を都道府県別に集計して上位7県の円グラフを作成しています。 ちなみに「死亡者数」は日別の人数ではなく累計で格納されています。 なので最後に集計した人数をそのまま順位として使うことができます。 行3ではDataFrameのmax()メソッドで最終集計日を取得しています。 行4ではDataFrameのデータを最終集計日だけに絞り込んでいます。 行5ではDataFrameのgroupby()メソッドで列「prefecture」をグループ化しています。 さらにDataFrameのsum()メソッドで列「total_deaths」を集計しています。 そして最後にDataFrameのsort_values()メソッドで死亡累計を降順に並べ替えています。 これで変数「desc_prefs」には列「prefecture, total_deaths」のSeriesが格納されます。
    # 3) Draw a pie chart for total_deaths
    # Get last date to see which prefectures have the most deaths currently
    last_date = df['date'].max()
    df_last_date = df[ df['date'] == last_date ]
    desc_prefs = df_last_date.groupby('prefecture')['total_deaths'].sum().sort_values(ascending=False)	
    desc_prefs
    # Generate lables and values for the pie chart
    labels = []
    values = []
    pref_count = 7  
    other_total = 0
    for pref in desc_prefs.index:
        if pref_count > 0:
            labels.append(pref)
            values.append(desc_prefs[pref])
            pref_count -= 1
        else:
            other_total += desc_prefs[pref]
    labels.append("Other")
    values.append(other_total)
    # Draw a pie cahrt
    wedge_dict = {
        'edgecolor': 'black',
        'linewidth': 2        
    }
    explode =  (0, 0, 0, 0, 0, 0, 0.1, 0) 
    plt.figure(figsize=(10,8))
    plt.pie(
        values, 
        labels=labels, 
        explode=explode, 
        autopct='%1.1f%%', 
        textprops={'color':'w'},
        wedgeprops=wedge_dict)
    plt.title('COVID-19 Total Deaths\n(累計死亡者数)', color='w', fontsize=18)
    
    plt.legend(
        fontsize=16,
        labels=['大阪','東京','北海道','兵庫','神奈川','愛知','埼玉','その他'] ,   
        loc='center right',
        bbox_to_anchor=(1, 0, 0.5, 1)
        )
    click image to zoom!
    図9
    図9は実行結果です。 死亡累計が多い順に大阪(17.1%)、東京(15.9%)、北海道(8.7%)、兵庫(8.1%)、神奈川(7.1%)、愛知(6.4%)、埼玉(5.6%)の順になっています。 意外ですが北海道が3位になっています。私の住んでいる埼玉は7位です。
  5. すべてのコードをまとめて掲載

    最後にこれまで解説したすべてのコードをまとめて掲載しましたので参考にしてください。 厚労省のサイトからCOVID-19のCSVファイルを取り込んでクリーンナップする。

    Version 1
    
    # Article013_Pandas Merge COVIC19 files Japan by ken(1).py V1
    # Data Source: https://www.mhlw.go.jp/stf/covid-19/open-data.html
    # csv files: 
    # newly_confirmed_cases_daily.csv 
    # requiring_inpatient_care_etc_daily.csv
    # deaths_cumulative_daily.csv 
    # severe_cases_daily.csv 
    # pcr_tested_daily.csv 
    # latlng_data_center.csv 
    # %%
    
    # Merge COVID-19 Data Files
    
    # Import the necessary libraries  
    import pandas as pd
    from pandas.core.frame import DataFrame
    import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # %%
    # 1) Load the csv files 
    csv1 = 'https://covid19.mhlw.go.jp/public/opendata/newly_confirmed_cases_daily.csv'
    raw1 = pd.read_csv(csv1)
    
    csv2 = 'https://www.mhlw.go.jp/content/pcr_tested_daily.csv'   # Exclude Prefecture (ken)
    raw2 = pd.read_csv(csv2)
    
    csv3 = 'https://covid19.mhlw.go.jp/public/opendata/deaths_cumulative_daily.csv'
    raw3 = pd.read_csv(csv3)
    
    csv4 = 'https://covid19.mhlw.go.jp/public/opendata/severe_cases_daily.csv'
    raw4 = pd.read_csv(csv4)
    
    csv5 = 'data/csv/covid-19/japan/latlng_data_center.csv'
    raw5 = pd.read_csv(csv5)
    
    raw1.to_csv('data/csv/covid-19/japan/newly_confirmed_cases_daily.csv', index=False)
    raw2.to_csv('data/csv/covid-19/japan/pcr_tested_daily.csv', index=False)
    raw3.to_csv('data/csv/covid-19/japan/deaths_cumulative_daily.csv', index=False)
    raw4.to_csv('data/csv/covid-19/japan/severe_cases_daily.csv', index=False)
    
    print('1) Load the csv files completed!')
    
    # %%
    
    # 2) Rename Column names
    raw1.set_axis(['date', 'prefecture', 'new_cases'], axis=1, inplace=True)
    raw2.set_axis(['date', 'new_tests'], axis=1, inplace=True)
    raw3.set_axis(['date', 'prefecture','total_deaths'], axis=1, inplace=True)
    raw4.set_axis(['date', 'prefecture','severe_cases'], axis=1, inplace=True)
    
    # 2-1) Convert str to datetime
    raw1['date'] = pd.to_datetime(raw1['date'])
    raw2['date'] = pd.to_datetime(raw2['date'])
    raw3['date'] = pd.to_datetime(raw3['date'])
    raw4['date'] = pd.to_datetime(raw4['date'])
    
    # 3) Add a file_id field
    raw1['file_id'] = 'new_cases'
    raw2['file_id'] = 'new_tests'
    raw3['file_id'] = 'tot_deaths'
    raw4['file_id'] = 'new_severe_cases'
    raw5['file_id'] = 'latlng_data'
    
    print('2-3) Rename Column names / Convert date / Add a file id completed!')
    
    # %%
    
    # 4) Add daily or total fields
    
    # 4-1) raw1 newly_confirmed_cases_daily.csv : add a total_cases field
    
    prefs = raw1['prefecture'].unique().tolist()
    #print(prefs)
    del prefs[0]    # Remove 'ALL' from the list
    #print(prefs)
    #prefs = ['Aichi']
    
    for pref in prefs:
        filter_by = (raw1['prefecture'] == pref) 
        dfx = raw1[filter_by]
        dfx.sort_values(by=['date'], inplace=True)
        dfx['total_cases'] = dfx['new_cases'].cumsum()  
        #csv = f'data/csv/covid-19/japan/newly_confirmed_cases_daily({pref}).csv'
        #dfx.to_csv(csv, index=False)
        for index, row in dfx.iterrows():
            filter_by = (raw1['prefecture'] == row.prefecture) & (raw1['date'] == row.date)
            raw1.loc[filter_by, 'total_cases'] = row.total_cases
    
    #raw1.to_csv('data/csv/covid-19/japan/newly_confirmed_cases_daily(1).csv', index=False)
    
    #print(raw1.tail())
    print('4-1) Add a total_cases field complete!')
    
    
    # %%
    
    # 4-2) raw4 severe_cases_daily.csv : add a total_severe_cases field
    
    prefs = raw4['prefecture'].unique().tolist()
    #print(prefs)
    del prefs[0]    # Remove 'ALL' from the list
    #print(prefs)
    #prefs = ['Aichi']
    
    for pref in prefs:
        filter_by = (raw4['prefecture'] == pref) 
        dfx = raw4[filter_by]
        dfx.sort_values(by=['date'], inplace=True)
        dfx['total_severe_cases'] = dfx['severe_cases'].cumsum()  
        #csv = f'data/csv/covid-19/japan/severe_cases_daily({pref}).csv'
        #dfx.to_csv(csv, index=False)      
        for index, row in dfx.iterrows():
            filter_by = (raw4['prefecture'] == row.prefecture) & (raw4['date'] == row.date)
            raw4.loc[filter_by, 'total_severe_cases'] = row.total_severe_cases
    
    #raw4.to_csv('data/csv/covid-19/japan/severe_cases_daily(1).csv', index=False)
    
    #print(raw4.tail())
    print('4-2) Add a total_severe_cases field complete!')
    
    # %%
    
    # 4-3) raw3 deaths_cumulative_daily.csv : add a new_deahts filed
    
    prefs = raw3['prefecture'].unique().tolist()
    #print(prefs)
    del prefs[0]    # Remove 'ALL' from the list
    #print(prefs)
    #prefs = ['Aichi']
    
    for pref in prefs:
        filter_by = (raw3['prefecture'] == pref)
        dfx = raw3[filter_by] 
        dfx.sort_values(by=['date'], inplace=True)
        dfx['new_deaths'] = dfx['total_deaths'].diff() 
    
        first_date = dfx['date'].min()
        filter_by = (dfx['date'] == first_date)
        dfy = dfx[filter_by]
        filter_by = ( dfx['date'] == first_date )
        dfx.loc[filter_by, 'new_deaths'] = dfy['total_deaths'] 
    
        #csv = f'data/csv/covid-19/japan/deaths_cumulative_daily({pref}).csv'
        #dfx.to_csv(csv, index=False)    
        for index, row in dfx.iterrows():
            filter_by = (raw3['prefecture'] == row.prefecture) & (raw3['date'] == row.date)
            raw3.loc[filter_by, 'new_deaths'] = row.new_deaths
    
    #raw3.to_csv('data/csv/covid-19/japan/deaths_cumulative_daily(1).csv', index=False)
    
    print('4-3) Add a new_deaths field complete!')
    
    # %%
    
    # 5) Merge the CSV files
    raw = pd.concat([raw1, raw2], ignore_index=True, axis=0)
    raw = pd.concat([raw, raw3], ignore_index=True, axis=0)
    raw = pd.concat([raw, raw4], ignore_index=True, axis=0)
    raw = pd.concat([raw, raw5], ignore_index=True, axis=0)
    
    print('5) Merge the CSV files completed!')
    
    # %%
    
    # 6) Replace all NaN values with 2019/1/1, N/A, 0
    
    replace_values = {
        'date':'2019/1/1',
        'prefecture': 'N/A',
        'new_cases': 0, 
        'severe_cases': 0,     
        'new_tests': 0, 
        'new_deaths': 0,
        'total_cases': 0,
        'total_severe_cases': 0,
        'total_deaths': 0,  
        'lan': 0, 'long': 0
        }
    raw.fillna(value=replace_values, inplace=True)
    raw.isnull().sum().sum()
    
    print('6) Replace all NaN values with 2019/1/1, N/A, 0 completed!')
    
    # Drop rows if the prefecture == 'ALL'
    
    index_no = raw[ raw['prefecture'] == 'ALL' ].index 
    raw.drop(index_no, inplace=True)
    #raw.head()
    
    # %%
    
    # 7) Update all lan, long if value is 0
    
    raw5.set_index('prefecture', inplace=True)
    cnt = 0
    
    for index, row in raw5.iterrows():
        #print(f'Update raw {index}, lan={row.lan}, long={row.long}')
        raw.loc[ raw['prefecture'] == index, ['lan', 'long'] ] = [row.lan, row.long] 
        #cnt += 1
        #if cnt > 5:
        #    break
    
    raw5.reset_index(inplace=True)
    #csv_file = 'data/csv/covid-19/japan/combined(2).csv'
    #raw.to_csv(csv_file, index=False) 
    
    print('7) Merging of csv files has been completed!')
    
    # %%
    
    # 8-1) raw4 severe_cases_daily.csv : update total_severe_cases, severe_cases fields for raw
    
    prefs = raw4['prefecture'].unique().tolist()
    #print(prefs)
    
    for pref in prefs:
        filter_by = (raw4['prefecture'] == pref) 
        dfx = raw4[filter_by]
        dfx.sort_values(by=['date'], inplace=True)      
        for index, row in dfx.iterrows():
            filter_by = (raw['file_id'] == 'new_cases') & (raw['prefecture'] == row.prefecture) & (raw['date'] == row.date)
            raw.loc[filter_by, ['total_severe_cases', 'severe_cases']] = [row.total_severe_cases, row.severe_cases]
    
    #print(raw4.tail())
    
    print('8-1) Update total_severe_cases / severe_case fields completed!')
    
    # %%
    
    # 8-2) raw3 deaths_cumulative_daily.csv : update total_deaths, new_deaths fields for raw
    
    prefs = raw3['prefecture'].unique().tolist()
    #print(prefs)
    
    for pref in prefs:
        filter_by = (raw3['prefecture'] == pref)
        dfx = raw3[filter_by]
        dfx.sort_values(by=['date'], inplace=True)
        for index, row in dfx.iterrows():
            filter_by = (raw['file_id'] == 'new_cases' ) & (raw['prefecture'] == row.prefecture) & (raw['date'] == row.date)
            raw.loc[filter_by, ['total_deaths', 'new_deaths']] = [row.total_deaths, row.new_deaths]
    
    print('8-2) Update total_deaths /new_deaths fields completed!')
    
    csv_file = 'data/csv/covid-19/japan/combined.csv'
    raw.to_csv(csv_file, index=False) 
    
    print('9) Merging of csv files has been completed!')
    
    # %%
    
    厚労省のサイトからCOVID-19のCSVファイルを取り込んでクリーンナップする。

    Version 2
    
    # Article013_Pandas Merge COVIC19 files Japan by ken(2).py V2
    # Data Source: https://www.mhlw.go.jp/stf/covid-19/open-data.html
    # csv files: 
    # newly_confirmed_cases_daily.csv 
    # requiring_inpatient_care_etc_daily.csv
    # deaths_cumulative_daily.csv 
    # severe_cases_daily.csv 
    # pcr_tested_daily.csv 
    # latlng_data_center.csv 
    # %%
    
    # 0) Merge COVID-19 Data Files
    
    # Import the necessary libraries  
    import pandas as pd
    from pandas.core.frame import DataFrame
    import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import numpy as np
    import warnings
    warnings.simplefilter('ignore')
    
    # %%
    # 1) Load the csv files 
    csv1 = 'https://covid19.mhlw.go.jp/public/opendata/newly_confirmed_cases_daily.csv'
    raw1 = pd.read_csv(csv1)
    
    csv2 = 'https://www.mhlw.go.jp/content/pcr_tested_daily.csv'   # Exclude Prefecture (ken)
    raw2 = pd.read_csv(csv2)
    
    csv3 = 'https://covid19.mhlw.go.jp/public/opendata/deaths_cumulative_daily.csv'
    raw3 = pd.read_csv(csv3)
    
    csv4 = 'https://covid19.mhlw.go.jp/public/opendata/severe_cases_daily.csv'
    raw4 = pd.read_csv(csv4)
    
    raw1.to_csv('data/csv/covid-19/japan/newly_confirmed_cases_daily.csv', index=False)
    raw2.to_csv('data/csv/covid-19/japan/pcr_tested_daily.csv', index=False)
    raw3.to_csv('data/csv/covid-19/japan/deaths_cumulative_daily.csv', index=False)
    raw4.to_csv('data/csv/covid-19/japan/severe_cases_daily.csv', index=False)
    
    print('1) Load the csv files completed!')
    
    # %%
    
    # 2) Rename Column names
    raw1.set_axis(['date', 'prefecture', 'new_cases'], axis=1, inplace=True)
    raw3.set_axis(['date', 'prefecture','total_deaths'], axis=1, inplace=True)
    raw4.set_axis(['date', 'prefecture','severe_cases'], axis=1, inplace=True)
    
    # 2-1) Convert str to datetime
    raw1['date'] = pd.to_datetime(raw1['date'])
    raw3['date'] = pd.to_datetime(raw3['date'])
    raw4['date'] = pd.to_datetime(raw4['date'])
    
    # 2-2) Remove ALL rows
    filter_by = (raw1['prefecture'] == 'ALL')
    #print(raw1[filter_by].index)
    raw1.drop(raw1[filter_by].index, inplace=True)
    
    filter_by = (raw3['prefecture'] == 'ALL')
    #print(raw3[filter_by].index)
    raw3.drop(raw3[filter_by].index, inplace=True)
    
    filter_by = (raw4['prefecture'] == 'ALL')
    #print(raw4[filter_by].index)
    raw4.drop(raw4[filter_by].index, inplace=True)
    
    print('2) Rename Column names / Convert date / Remove AlL completed!')
    
    # %%
    
    # 3) Add daily or total fields
    
    # 3-1) raw1 newly_confirmed_cases_daily.csv : add a total_cases field
    
    prefs = raw1['prefecture'].unique().tolist()
    #print(prefs)
    del prefs[0]    # Remove 'ALL' from the list
    #print(prefs)
    #prefs = ['Aichi','Akita']
    dfx_prefs = []
    
    for pref in prefs:
        filter_by = (raw1['prefecture'] == pref) 
        df = raw1[filter_by]
        df.sort_values(by=['prefecture','date'], inplace=True)       # sort by prefecture, date
        dfx = df[['prefecture','date','new_cases']]         # select prefecture, date, new_cases
        dfx['total_cases'] = df['new_cases'].cumsum()       # calculate total_cases by date  
        #csv = f'data/csv/covid-19/japan/newly_confirmed_cases_daily_dfx({pref}).csv'
        #dfx.to_csv(csv, index=False)
        dfx_prefs.append(dfx)
    
    raw1x = pd.concat(dfx_prefs, ignore_index=True, axis=0)
    raw1x.to_csv('data/csv/covid-19/japan/newly_confirmed_cases_daily(0).csv', index=False)
    
    #print(raw1.tail())
    print('3-1) Add a total_cases field complete!')
    
    
    # %%
    
    # 3-2) raw4 severe_cases_daily.csv : add a total_severe_cases field
    
    prefs = raw4['prefecture'].unique().tolist()
    #print(prefs)
    del prefs[0]    # Remove 'ALL' from the list
    #print(prefs)
    #prefs = ['Aichi']
    dfx_prefs = []
    
    for pref in prefs:
        filter_by = (raw4['prefecture'] == pref) 
        df = raw4[filter_by]
        df.sort_values(by=['date'], inplace=True)           # sort by prefecture, date
        dfx = df[['prefecture','date','severe_cases']]     # select prefecture, date, severe_cases
        dfx['total_severe_cases'] = df['severe_cases'].cumsum()  # calculate total_severe_cases 
        #csv = f'data/csv/covid-19/japan/severe_cases_daily({pref}).csv'
        #dfx.to_csv(csv, index=False)      
        dfx_prefs.append(dfx)
    
    raw4x = pd.concat(dfx_prefs, ignore_index=True, axis=0)
    raw4x.to_csv('data/csv/covid-19/japan/severe_cases_daily(0).csv', index=False)
    
    #print(raw4.tail())
    print('3-2) Add a total_severe_cases field complete!')
    
    # %%
    
    # 3-3) raw3 deaths_cumulative_daily.csv : add a new_deahts filed
    
    prefs = raw3['prefecture'].unique().tolist()
    #print(prefs)
    del prefs[0]    # Remove 'ALL' from the list
    #print(prefs)
    #prefs = ['Aichi']
    dfx_prefs = []
    
    for pref in prefs:
        filter_by = (raw3['prefecture'] == pref)
        df = raw3[filter_by] 
        df.sort_values(by=['date'], inplace=True)
        dfx = df[['prefecture','date','total_deaths']] # select prefecture, date, total_deaths
        dfx['new_deaths'] = df['total_deaths'].diff()    # calculate new_deaths
    
        first_date = dfx['date'].min()
        filter_by = (dfx['date'] == first_date)
        dfy = dfx[filter_by]
        filter_by = ( dfx['date'] == first_date )
        dfx.loc[filter_by, 'new_deaths'] = dfy['total_deaths'] 
        #csv = f'data/csv/covid-19/japan/deaths_cumulative_daily({pref}).csv'
        #dfx.to_csv(csv, index=False)    
        dfx_prefs.append(dfx)
    
    raw3x = pd.concat(dfx_prefs, ignore_index=True, axis=0) 
    raw3x.to_csv('data/csv/covid-19/japan/deaths_cumulative_daily(0).csv', index=False)
    
    print('3-3) Add a new_deaths field complete!')
    
    # %%
    
    # 4) Merge the CSV files
    raw = pd.merge(raw1x, raw3x, how='outer')
    raw = pd.merge(raw, raw4x, how='outer')
    
    csv_file = 'data/csv/covid-19/japan/combined_v2(merge).csv'
    raw.to_csv(csv_file, index=False) 
    
    print('4) Merge the CSV files completed!')
    
    # %%
    
    # 5) Replace all NaN values with 2019/1/1, N/A, 0
    
    replace_values = {
        'date':'2019/1/1',
        'prefecture': 'N/A',
        'new_cases': 0, 
        'severe_cases': 0,     
        'new_tests': 0, 
        'new_deaths': 0,
        'total_cases': 0,
        'total_severe_cases': 0,
        'total_deaths': 0  
        }
    raw.fillna(value=replace_values, inplace=True)
    raw.isnull().sum().sum()
    
    print('5) Replace all NaN values with 2019/1/1, N/A, 0 completed!')
    
    # %%
    
    # 6) Drop rows if the prefecture == 'ALL'
    
    index_no = raw[ raw['prefecture'] == 'ALL' ].index 
    raw.drop(index_no, inplace=True)
    #raw.head()
    
    print('6) Drop rows if the prefecture == ALL completed!')
    
    # %%
    
    # 7) Create a merged csv file
    csv_file = 'data/csv/covid-19/japan/combined_v2.csv'
    raw.to_csv(csv_file, index=False) 
    
    print('7) Merging of csv files has been completed!')
    
    # %%
    
    一元化したCOVID-19のデータを解析する。
    
    # Data Source: https://www.mhlw.go.jp/stf/covid-19/open-data.html
    # csv files: data/csv/covid-19/japan/combined.csv
    # %%
    
    # Grouping & Pivoting in Pandas
    
    # Import the necessary libraries  
    import pandas as pd
    #from pandas.core.frame import DataFrame
    #import pandas_datareader.data as web    # pip install pandas_datareader
    import matplotlib.pyplot as plt
    import matplotlib.style as style
    import numpy as np
    
    # 1) Load the csv file cases 
    csv_file = 'data/csv/covid-19/japan/combined.csv'
    raw = pd.read_csv(csv_file) 
    df = raw
    
    # Convert str to datetime
    df['date'] = pd.to_datetime(df['date'])
    
    # %%
    
    # Set the font to support Japanese
    plt.rcParams['font.family'] = 'Yu Gothic'  # Meiryo, Yu Gothic
    # 1) Draw a pie chart for new_cases
    # Get to see which prefectures have the most cases currently
    desc_prefs = df.groupby('prefecture')['new_cases'].sum().sort_values(ascending=False)	
    desc_prefs
    # Generate lables and values for the pie chart
    labels = []
    values = []
    pref_count = 5   # 5+1=6
    other_total = 0
    for pref in desc_prefs.index:
        if pref_count > 0:
            labels.append(pref)
            values.append(desc_prefs[pref])
            pref_count -= 1
        else:
            other_total += desc_prefs[pref]
    labels.append("Other")
    values.append(other_total)
    # Draw a pie cahrt
    wedge_dict = {
        'edgecolor': 'black', # black
        'linewidth': 2  # 2      
    }
    explode = (0, 0, 0, 0.1, 0, 0)  # 6
    plt.figure(figsize=(10,8))
    
    plt.pie(
        values, 
        labels=labels, 
        explode=explode, 
        autopct='%1.1f%%', 
        textprops={'color':'w'},
        wedgeprops=wedge_dict)
    
    plt.title('COVID-19 Cases\n(発症者数)', color='w', fontsize=18)
    #plt.legend(fontsize=15, loc='center right')
    
    plt.legend(
        fontsize=16,
        labels=['東京','大阪','神奈川','埼玉','愛知','その他'] ,   
        loc='center right',
        bbox_to_anchor=(1, 0, 0.5, 1)
        )
    
    # %%
    
    # 2) Draw a pie chart for severe_cases
    
    # Get to see which prefectures have the most severe cases currently
    desc_prefs = df.groupby('prefecture')['severe_cases'].sum().sort_values(ascending=False)	
    desc_prefs
    
    # Generate lables and values for the pie chart
    labels = []
    values = []
    
    pref_count = 5   # 5+1=6
    
    other_total = 0
    
    for pref in desc_prefs.index:
        if pref_count > 0:
            labels.append(pref)
            values.append(desc_prefs[pref])
            pref_count -= 1
        else:
            other_total += desc_prefs[pref]
    
    labels.append("Other")
    values.append(other_total)
    
    # Draw a pie cahrt
    
    wedge_dict = {
        'edgecolor': 'black',
        'linewidth': 2        
    }
    
    explode = (0, 0, 0, 0, 0.1, 0)  # 6
    
    plt.figure(figsize=(10,8))
    
    plt.pie(
        values, 
        labels=labels, 
        explode=explode, 
        autopct='%1.1f%%', 
        textprops={'color':'w'},
        wedgeprops=wedge_dict)
    
    plt.title('COVID-19 Severe Cases\n(重症者数)', color='w', fontsize=18)
    
    #plt.legend(fontsize=15, loc='center right')
    
    plt.legend(
        fontsize=16,
        labels=['大阪','東京','神奈川','兵庫','埼玉','その他'] ,   
        loc='center right',
        bbox_to_anchor=(1, 0, 0.5, 1)
        )
    
    # %%
    
    # 3) Draw a pie chart for total_deaths
    
    # Get last date to see which prefectures have the most deaths currently
    last_date = df['date'].max()
    df_last_date = df[ df['date'] == last_date ]
    desc_prefs = df_last_date.groupby('prefecture')['total_deaths'].sum().sort_values(ascending=False)	
    desc_prefs
    
    # Generate lables and values for the pie chart
    labels = []
    values = []
    
    pref_count = 7   # 7+1=8
    
    other_total = 0
    
    for pref in desc_prefs.index:
        if pref_count > 0:
            labels.append(pref)
            values.append(desc_prefs[pref])
            pref_count -= 1
        else:
            other_total += desc_prefs[pref]
    
    labels.append("Other")
    values.append(other_total)
    
    # Draw a pie cahrt
    
    wedge_dict = {
        'edgecolor': 'black',
        'linewidth': 2        
    }
    
    explode =  (0, 0, 0, 0, 0, 0, 0.1, 0)  # 8
    
    plt.figure(figsize=(10,8))
    
    plt.pie(
        values, 
        labels=labels, 
        explode=explode, 
        autopct='%1.1f%%', 
        textprops={'color':'w'},
        wedgeprops=wedge_dict)
    
    plt.title('COVID-19 Total Deaths\n(累計死亡者数)', color='w', fontsize=18)
    
    #plt.legend(fontsize=15, loc='center right')
    
    plt.legend(
        fontsize=16,
        labels=['大阪','東京','北海道','兵庫','神奈川','愛知','埼玉','その他'] ,   
        loc='center right',
        bbox_to_anchor=(1, 0, 0.5, 1)
        )