Python で COVID-19 のコロプレス図を作成する（folium版）

# はじめに
簡単なコロプレス図を作りたいと思ったときに、いろいろと調べたので備忘録代わりに記録しておく。以下、参考サイト。

- foliumn の使い方
    - [Folium Official Document](https://python-visualization.github.io/folium/)
    - [foliumの基本的な使い方とオープンデータ活用](https://qiita.com/Kumanuron-1910/items/12ce7aa02922927de2f4)
    - [foliumを使って東京23区ラーメンスコアを可視化する](https://qiita.com/xkent/items/d068fc504c8cef217ca8)
    - [Pythonで特定の国を特定の色で分類したインタラクティブな世界地図を作る (folium)](https://qiita.com/sentencebird/items/8b5198bba42a80642520)
- 使用したデータ
    - [CSSEGISandData/COVID-19(感染者数のデータ)](https://github.com/CSSEGISandData/COVID-19)
    - [Country Polygons as GeoJSON](https://datahub.io/core/geo-countries)

また、cartopy でのコロプレス図の作り方は[「Python で COVID-19 のコロプレス図を作成する（cartopy版）」](https://qiita.com/ryamamoto0406/items/ef24a50e8f8732c0b8a0)に書いてあるので、もし興味があれば参照してください。

# folium のインストール
いつもの通り、pip, conda でインストールできる。

- pip の場合

```bash
$ pip install folium
```

- conda の場合

```bash
$ conda install folium -c conda-forge
```

いくつかの関数は、numpy, pandas, geopandas, altair, etc.などの他ライブラリに依存しているようなので、それらも必要に応じてインストールする必要がある。（※geopandas の conda でのインストールについては[「Python で COVID-19 のコロプレス図を作成する（cartopy版）」](https://qiita.com/ryamamoto0406/items/ef24a50e8f8732c0b8a0)に注意を載せている。）

# 前処理
### 国ごとの合算
Covid-19 の感染者数が地域ごとに記録されているので、これを国ごとのデータになるよう処理を行う。(以下、2022年2月17日のデータで行う。)

```python:国ごとの合算
# 必要なモジュールのインポート
import pandas as pd

# データの取得
df = pd.read_csv("./02-17-2022.csv")

# 国ごとに合算しなおす
df_sum = df.groupby("Country_Region").sum()[["Confirmed", "Deaths"]].copy()
df_sum.reset_index(inplace=True)

# 致死率を計算
df_sum["CFR"] = df_sum["Deaths"] / df_sum["Confirmed"] * 100

# 結果の表示
print(df_sum.head())
```

出力は以下の通り。

| |Country_Region|Confirmed|Deaths|CFR|
|---|---|---|---|---|
|0|Afghanistan|171673|7524|4.382751|
|1|Albania|269301|3430|1.273668|
|2|Algeria|263369|6772|2.571297|
|3|Andorra|37522|150|0.399765|
|4|Angola|98585|1899|1.926257|

### GeoJSON と国名の表記ゆれの確認
GeoJSON を geopandas を用いて中身を確認し、国名が一致するのかの確認と、一致しない場合の処理を行う。#ここが手作業で面倒なので、どなたか頭の良い方法が有ったら教えて下さい…。

```python:国名の表記ゆれの確認
# 必要なモジュールのインポート
import geopandas as gpd

# GeoJSON の読み込み
gdf = gpd.read_file('./countries.geojson')

# 集合演算を使って Covid-19 データの一致しない国名を抜き出す
set_covid_19 = set(df_sum["Country_Region"])
set_geojson = set(gdf["ADMIN"])
set_diff = set_covid_19 - set_geojson

# 結果の表示
print(set_diff)
```

```python:出力
{'Micronesia', 'Eswatini', 'Cabo Verde', "Cote d'Ivoire", 'Guinea-Bissau', 'Czechia', 'Burma', 'Timor-Leste', 'Summer Olympics 2020', 'Winter Olympics 2022', 'Diamond Princess', 'Holy See', 'North Macedonia', 'Tanzania', 'Bahamas', 'US', 'Congo (Kinshasa)', 'Serbia', 'MS Zaandam', 'Congo (Brazzaville)', 'West Bank and Gaza', 'Taiwan*', 'Korea, South'}
```

国の名前の他に、地域やクラスターが発生したクルーズ船の名前なども含まれている。これらを手作業で修正。`set_geojson` の名前になるよう修正していく。

```python:国名の修正
# 元の国名を保存
df_sum["Country_Region_conv"] = df_sum["Country_Region"]

# 以下、手作業で修正
df_sum.loc[
    (df_sum["Country_Region"] == "Bahamas"), "Country_Region_conv"
] = "The Bahamas"
df_sum.loc[(df_sum["Country_Region"] == "Burma"), "Country_Region_conv"] = "Myanmar"
df_sum.loc[
    (df_sum["Country_Region"] == "Cabo Verde"), "Country_Region_conv"
] = "Cape Verde"
df_sum.loc[
    (df_sum["Country_Region"] == "Congo (Brazzaville)"), "Country_Region_conv"
] = "Republic of Congo"
df_sum.loc[
    (df_sum["Country_Region"] == "Congo (Kinshasa)"), "Country_Region_conv"
] = "Democratic Republic of the Congo"
df_sum.loc[
    (df_sum["Country_Region"] == "Cote d'Ivoire"), "Country_Region_conv"
] = "Ivory Coast"
df_sum.loc[
    (df_sum["Country_Region"] == "Czechia"), "Country_Region_conv"
] = "Czech Republic"
df_sum.loc[
    (df_sum["Country_Region"] == "Eswatini"), "Country_Region_conv"
] = "Swaziland"
df_sum.loc[
    (df_sum["Country_Region"] == "Guinea-Bissau"), "Country_Region_conv"
] = "Guinea Bissau"
df_sum.loc[(df_sum["Country_Region"] == "Holy See"), "Country_Region_conv"] = "Vatican"
df_sum.loc[
    (df_sum["Country_Region"] == "Korea, South"), "Country_Region_conv"
] = "South Korea"
df_sum.loc[
    (df_sum["Country_Region"] == "Micronesia"), "Country_Region_conv"
] = "Federated States of Micronesia"
df_sum.loc[
    (df_sum["Country_Region"] == "North Macedonia"), "Country_Region_conv"
] = "Macedonia"
df_sum.loc[
    (df_sum["Country_Region"] == "Serbia"), "Country_Region_conv"
] = "Republic of Serbia"
df_sum.loc[(df_sum["Country_Region"] == "Taiwan*"), "Country_Region_conv"] = "Taiwan"
df_sum.loc[
    (df_sum["Country_Region"] == "Tanzania"), "Country_Region_conv"
] = "United Republic of Tanzania"
df_sum.loc[
    (df_sum["Country_Region"] == "Timor-Leste"), "Country_Region_conv"
] = "East Timor"
df_sum.loc[
    (df_sum["Country_Region"] == "US"), "Country_Region_conv"
] = "United States of America"

# 修正できているかの確認
set_covid_19_conv = set(df_sum["Country_Region_conv"])
set_diff_conv = set_covid_19_conv - set_geojson

print(set_diff_conv)
```

```python:出力
{'MS Zaandam', 'Diamond Princess', 'West Bank and Gaza', 'Summer Olympics 2020', 'Winter Olympics 2022'}
```

国境ファイルのデータに該当しないものが残った。これらのプロットは諦める事とする。

# コロプレス図の作成
cartopy と違い、folium には Coropleth という関数が存在している。

```python:コロプレス図作成
# 必要なモジュールのインポート
from folium import Map, LayerControl, Choropleth

# 地図の作成（中心は日本）
m = Map(location=[35.658581, 139.745433], zoom_start = 2)

# コロプレス図の作成
Choropleth(
    geo_data="./countries.geojson",  # GeoJSONファイル
    name="choropleth",  # map名(何でもよい)
    data=df_sum,  # Covid-19の致死率と国名が含まれているデータ
    columns=["Country_Region_conv", "CFR"],  # データのkey列（国名）とvalue列（致死率）を指定
    key_on="properties.ADMIN",  # GeoJSONファイル内のkey（国名）を指定
    fill_opacity=0.7,
    line_opacity=0.2,
    line_color="blue",
    fill_color="Reds",
).add_to(m)
LayerControl().add_to(m)

# 図の保存
m.save('coropleth.html')
```

![coropleth.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1077734/de62e10d-28ff-7309-1376-4962cfa63261.png)

これでカラーバー付きコロプレス図を作成することができた。cartopy に比べれるとだいぶ楽に作れる。北朝鮮、グリーンランド、トルクメニスタンなどではデータが無いので、黒く塗りつぶされている。

# おわりに
今回は Covid-19 の致死率を題材にコロプレス図を作成してみた。GeoJSONとデータさえあれば、国毎でなく地域ごとにプロットを作ることも可能である。