東京都新型コロナウイルス感染症(COVID-19)対策サイトのオープンデータをGoogle Colabで可視化する

# 概要
[東京都新型コロナウイルス感染症(COVID-19)対策サイト](https://stopcovid19.metro.tokyo.lg.jp/)にて、陽性患者数の日別推移が掲載されています。同時にこのデータは[オープンデータとしてCSVファイルで公開](https://catalog.data.metro.tokyo.lg.jp/dataset/t000010d0000000068)されているため、これを[Google Colab](https://colab.research.google.com/)のノートブック上で読み込み、Seabornで日別・年代別に可視化してみました。

別の切り口から推移を分析する際の土台としても使えるかと思い、ノートブックを公開します。

# ノートブックのリンク
GitHubに置いてあります。
https://github.com/nekodango/tokyo_stopcovid19_opendata

# ノートブックをGoogle Colabで実行する
1. 上記GitHubリンクから「tokyo_opendata_covid19_patients.ipynb」をクリックして開く

2. 「Open in Colab」バナーをクリックする
![Screenshot at 2020-04-01 00-18-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611740/ee0ee665-2987-d860-4420-c0c0013dc8ab.png)

3. 「ランタイム」> 「すべてのセルを実行」の順番でクリックする
![Screenshot at 2020-04-01 00-23-21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611740/7dc16b0b-cabe-ee80-cd5f-103cf699756f.png)

実行するたび、その時点での最新データを取得して集計・描画します。
(2020/3/31現在、[CSVデータの更新頻度は「毎日8：30更新」](https://catalog.data.metro.tokyo.lg.jp/dataset/t000010d0000000068)とのことです)

# 可視化結果
![heatmap_h.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611740/48e09794-1aa9-0781-d6c2-e84c6ebd89af.png)
この3連休(3/27〜3/29)を境にして、20代・30代の陽性患者の増加に拍車がかかっているように見えます。
元データのヘッダを見ると、この日付は「**発症**年月日」ではなく「**発表**年月日」なので、解釈には一応注意が必要かと。
 

# ノートブックでやったこと
## ライブラリの読み込み
```python
import pandas as pd
```

## データの取得
wgetを使ってCSVデータをダウンロードします。
Google Colabでコマンドを実行する際は、"!"を先頭に付けます。(マジックコマンド)

```shell

!wget https://stopcovid19.metro.tokyo.lg.jp/data/130001_tokyo_covid19_patients.csv
```

## CSVデータをPandas DataFrameに変換
df_patientsにダウンロードデータが入ります。

```python
df_patients = pd.read_csv('130001_tokyo_covid19_patients.csv')
df_patients['公表_年月日'] = pd.to_datetime(df_patients['公表_年月日'], format='%Y-%m-%d')
```

## データを見てみる
この段階では、陽性患者1名につき1行のデータとなっています。

```python
df_patients.head(5)
```
![Screenshot at 2020-03-31 23-40-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611740/a9959954-ac21-48a7-4b9c-ceba628bdbe8.png)

## 日別集計表を作成する
日付ごとの年代別陽性患者数を、集計表にまとめます。

```python
df_tmp = df_patients[['公表_年月日', '患者_年代']]
df_tmp['人数'] = 1
df_tmp2 = df_tmp.pivot(columns='患者_年代', values='人数' )
df_tmp = pd.concat([df_tmp['公表_年月日'], df_tmp2], axis=1).fillna(0)
df_tmp = df_tmp[['公表_年月日', '10歳未満', '10代',  '20代', '30代', '40代', '50代', '60代', '70代', '80代', '90代','不明']]
df_tmp = df_tmp.groupby('公表_年月日').sum()
df_dairy_patients = df_tmp.resample('D').mean().fillna(0)
```

## 日別集計表を見てみる
```python
df_dairy_patients
```
![Screenshot at 2020-03-31 23-46-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611740/02dd782f-08dd-5990-7900-5b65c5a64362.png)

## Seabornで日本語フォントを使えるようにする
Seabornで日本語を含んだグラフを描画できるよう、おまじないを唱えておきます。
これやっとかないと、日本語部分だけ「□」(いわゆる豆腐)で表示されます。

```python
!pip install japanize_matplotlib
import matplotlib.pyplot as plt
import japanize_matplotlib 
import seaborn as sns

sns.set(font="IPAexGothic")
```

## 日付の曜日を日本語表示にする準備
「03/31(Tue)」より「03/31(火)」の方がわかりやすいので、期間中の日本語日付をdate_labelに入れます。

```python
  week = {'Sun': '日', 'Mon': '月', 'Tue': '火', 'Wed': '水', 'Thu': '木', 'Fri': '金', 'Sat': '土'}
  date_monthday = list(df_dairy_patients.index.strftime('%m/%d'))
  date_week = [week[x] for x in list(df_dairy_patients.index.strftime('%a'))]
  date_label = [f'{monthday}({week})' for monthday, week in zip(date_monthday, date_week)]
```

## ヒートマップの作成(横バージョン)
縦軸に年代、横軸に日付をとった陽性患者数のヒートマップを描画してみます。

```python
# 画像のサイズを指定する
plt.figure(figsize=(30, 16))
# 横軸の日付を上部に持ってくる(デフォルトは下部)
plt.tick_params(axis='both', which='major', labelsize=10, labelbottom = False, bottom=False, top = False, labeltop=True)
# 横軸ラベル(xticklabels)に日本語表示の日付(date_label)を設定して、ヒートマップ描画する
sns.heatmap(df_dairy_patients.T, square=True, annot=True, cbar=False, cmap='Reds', linewidths=0.1, xticklabels=date_label)
```
前掲「可視化結果」のヒートマップが出力されます。

## ヒートマップの作成(縦バージョン)
縦軸に日付、横軸に年代をとった陽性患者数のヒートマップを描画します。
直近の変化が見やすいように、新しい日付ほど上に来るよう並び替えて描画しました。

```python
# 画像のサイズを指定する
plt.figure(figsize=(20, 30))
# 横軸の日付を上部に持ってくる(デフォルトは下部)
plt.tick_params(axis='both', which='major', labelsize=10, labelbottom = False, bottom=False, top = False, labeltop=True)
chart = sns.heatmap(df_dairy_patients.sort_index(ascending=False), square=True, annot=True, cbar=False, cmap='Reds', linewidths=0.1, yticklabels=list(reversed(date_label)))
# 横軸ラベルを斜め45度傾ける
_ = chart.set_xticklabels(chart.get_xticklabels(), rotation=45)
```
![download (コピー).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611740/d82b3013-2234-ce75-d3cc-5a2a13050846.png)


# まとめ
新型コロナウイルス感染症対策を行う方々(特に患者数推移のデータを分析する方々)にとって、この記事のコードおよび手法が参考になれば幸いです。