コロナウイルスの感染具合をseabornのヒートマップで表示してみた

#コロナの感染具合をseabornのヒートマップで表示してみた

##目的
コロナの各都道府県での広がり具合を視覚化する
ゴールはこれです。
![colona.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455102/81b7810d-7c39-7ec9-db71-0284eccb2897.png)

##方法
pythonのseabornを使用する。
感染者数データ(4/5まで)はこちら。https://toyokeizai.net/sp/visual/tko/covid19/
都道府県名データはこちら。https://gist.github.com/mugifly/d6e68a516de4a008687c
いろいろまとめてこちら。https://github.com/kyasby/colona.git


##ライブラリをインポート
```python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
```
`%matplotlib inline`はおまじないです。
numpyは`cumsum()`のためにインポートします。

##感染者数csvをインポート
```python
df = pd.read_csv("COVID-19.csv")
df = df[["受診都道府県", "居住都道府県", "人数", "発症日", "確定日"]]
df = df.rename(columns={"年代":"age", "性別":"sex", "受診都道府県":"hsp", "居住都道府県":"house"})
df
```
必要なカラムを抜き出し、同時にリネームします。
df[]にリストを渡すことで、そのカラムだけ抜き出すことができます。

`df.rename(columns={"old_columns_name":"new_name"},index={"old_index_name":"new_name"})`
などと辞書を渡すことで、カラム名やインデックス名を変更できます。

＊hspはhospitalです。

##日付作り
```python
for i, row in df.iterrows():
    if type(row["発症日"])==float:
        df.at[i, "発症日"] = row["確定日"]
    else:
        pass
df = df.rename(columns = {"発症日":"Date"})
```
ヒートマップの横軸を日付にしたいので、日付を取得します。
しかし、以下のように「発症日」にはNaNが含まれているので、その場合は「確定日」で置き換えます。

|    hsp     |     house      |人数| 発症日  | 確定日  |
|------------|----------------|---:|---------|---------|
|神奈川県    |神奈川県        |   1|1/3/2020 |1/15/2020|
|東京都      |中華人民共和国  |   1|1/14/2020|1/24/2020|
|東京都      |中華人民共和国  |   1|1/21/2020|1/25/2020|
|大阪府      |大阪府          |   1|1/20/2020|1/29/2020|
|不明        |中華人民共和国  |   1|1/29/2020|1/30/2020|
|千葉県      |中華人民共和国  |   1|NaN      |1/30/2020|

最後に、カラム名を「Date」に変更します。

NaNの判定を
`type(row["発症日"])==float`
このように書きましたが、もっと良い書き方があれば是非教えてください。

##都道府県のCSVをインポート
```python
todofuken = pd.read_csv("japan.csv", header=None)[0]
```

##hspの一部を置き換える

```python
df["hsp"].value_counts()
```
で、「hsp」の中身を確認すると、「羽田空港」や「不明」があることがわかります。

![スクリーンショット 2020-04-06 16.04.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455102/fe1c8c6c-81b8-49a8-3d7c-943289009da7.png)

```python
df["hsp"]= df["hsp"].apply(lambda x : "その他" if x not in list(todofuken) else x)
```
applyとラムダ関数を使い、df["hsp"]の中身を一部書き換えます。
都道府県名リストにない場合は、「その他」、ある場合はそのままの都道府県を入れます
applyとラムダ関数を使うときは、おそらくelseがないと構文エラーになります。（未確認）注意してください。

ここまででdfはこのようになっています。

|    hsp     |     house      |人数|  Date   | 確定日  |
|------------|----------------|---:|---------|---------|
|神奈川県    |神奈川県        |   1|1/3/2020 |1/15/2020|
|東京都      |中華人民共和国  |   1|1/14/2020|1/24/2020|
|東京都      |中華人民共和国  |   1|1/21/2020|1/25/2020|
|愛知県      |中華人民共和国  |   1|1/23/2020|1/26/2020|
|愛知県      |中華人民共和国  |   1|1/22/2020|1/28/2020|
|奈良県      |奈良県          |   1|1/14/2020|1/28/2020|
|北海道      |中華人民共和国  |   1|1/26/2020|1/28/2020|
|大阪府      |大阪府          |   1|1/20/2020|1/29/2020|


##ピボットにする
```python
pvt = df.pivot_table(index="hsp", columns="Date", values="人数").fillna(0)
pvt = pvt.rename(index = dict(zip(jpn[0], jpn[2]))).rename(index={"その他":"others"})
```

pandasにはpivot_tableというメソッドが用意されており、文字通りピボットテーブルを作成することができます。（エクセルいらずですね。）また、NaNを0で埋めておきます。

そして、北海道→hokkaidoなどとリネームします。僕の環境では、インデックス名やカラム名に日本語が含まれていると、文字が表示されません。何かインストールすると解決されるらしいですが、リネームで対応します。（より良い方法があれば是非、教えてください。）

jpn[0]の中身は、北海道、青森、など漢字の都道府県名です。
jpn[2]の中身は、hokkaido、aomoriなどローマ字の都道府県名です。

これらを`zip関数`でペアにし、`dict関数`で辞書にし、`rename関数`に渡します。
また、「その他」を「others」に変更します。

ここまでで、このようなデータフレームになっています。
![スクリーンショット 2020-04-06 0.42.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455102/c57ac185-d126-3a09-21c6-fe2c82e498cb.png)

##累積人数にする
```python
for i in range(len(pvt)):
    pvt.iloc[i]=pvt.iloc[i].cumsum()
```
pvtから１行ずつ取り出し、`numpy`の`cumsum()`関数で累積の人数にします。

このように、累積人数に更新されました。
![スクリーンショット 2020-04-06 0.46.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455102/ad78a85e-c2ad-271f-2903-a2b7b304516c.png)

##表示して、保存する
```python
plt.figure(figsize=(20,10))
sns.heatmap(pvt.iloc[:,-60:] , linewidths=0, cmap='Spectral', cbar=True, xticklabels=5)
plt.savefig("colona.png")
```

若い日付の日は、感染者が（幸い）ほとんどおらず表示しれても意味がないので６０日前から表示することにしました。
`:`(スライス)を使うことができます。例えば`10:20`であれば１０以上２０未満を示します。

こんな感じで、ヒートマップを表示させることができました。

![colona.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455102/81b7810d-7c39-7ec9-db71-0284eccb2897.png)