都道府県別「直近1週間の人口10万人あたりの感染者数」をクラスター分析

# ◎概要
教師なし機械学習のクラスター分析を用いて、都道府県ごとの「直近1週間の人口10万人あたりの感染者数」を5つのクラスターに分類して（期間ごと）、その分類結果を考察する。

# ◎目的
教師なし機械学習の勉強のため。
ちょっとしたデータをすぐにクラスター分析できるようになっておきたい。

## ○ Python実行環境
- Colaboratory

---
## ○ ソースコード

### GoogleDriveをｍount
> 画像保存先をGoogleDriveに

```python
from google.colab import drive
drive.mount('/content/drive')
%cd /content/drive/My Drive/Colab Notebooks
```

### Package Install
> 必要なパッケージをインストール

```
!pip install japanize_matplotlib
```
```python
import pandas as pd
import math
import numpy as np
import matplotlib.pyplot as plt
import japanize_matplotlib
from sklearn.cluster import KMeans
from sklearn.preprocessing import  StandardScaler
import datetime
```


### データ取得＆整形
> NHKのHPからCSVをDLしてきて、使いやすいようにデータを整形

```python
"""
データ取得
"""
def data_get (start, end):
  df = pd.read_csv('nhk_news_covid19_prefectures_daily_data.csv')
  df.columns.values
  rows = []
  date_list = df.query('都道府県コード == 1')['日付'].values.tolist()
  start_date = date_list.index(start)
  end_date = date_list.index(end) + 1
  print('start_date', start_date)
  print('end_date', end_date)
  labels = date_list[start_date:end_date]
  labels.insert(0, '都道府県名')
  for pref_code in range(1,48):
    cols = []
    data1 = df.query(f'都道府県コード == {pref_code}')['都道府県名'].values.tolist()[0]
    cols.insert(0,data1)
    data2 = df.query(f'都道府県コード == {pref_code}')['各地の直近1週間の人口10万人あたりの感染者数'].values.tolist()[start_date:end_date]
    cols.extend(0.0 if math.isnan(d) else d for d in data2)
    rows.append(cols)
  df_result = pd.DataFrame(rows, columns=labels)
  x_data = df_result.drop(labels=['都道府県名'], axis=1).values
  x_labels = df_result.drop(labels=['都道府県名'], axis=1).columns.values
  return df_result, x_data, x_labels
```

### クラスタリング
> 教師なし学習で分類

```python
"""
K-平均法
"""
def k_means(df, x_data, n_clusters):
  scaler = StandardScaler()
  x_scaled = scaler.fit_transform(x_data)
  kmeans = KMeans(n_clusters=n_clusters, random_state=0)
  kmeans.fit(x_scaled)
  cluster = kmeans.predict(x_scaled)
  df_cluster = df.copy()
  df_cluster['cluster'] = cluster
  return cluster, df_cluster
```

### グラフ表示＆画像保存
> クラスタリングした結果をグラフにプロットして、結果を画像として保存

```python
"""
グラフ表示
"""
def plot_view(cluster, df_cluster, graph_title, x_labels):
  data_labels = [datetime.datetime.strptime(l, '%Y/%m/%d') for l in x_labels]
  data_length = len(np.unique(cluster))
  cols_index = 2
  rows_index = math.ceil(data_length / cols_index)
  data_count = 0
  scale = 0.65
  fig = plt.figure(figsize=(cols_index*16*scale, rows_index*9*scale))
  plt.suptitle(graph_title, size='30')
  for row_i in range(rows_index):
    for col_i in range(cols_index): 
      if data_count < data_length:
        ax = fig.add_subplot(rows_index, cols_index, data_count+1)
        for v in df_cluster.query(f'cluster == {data_count}').values.tolist():
          ax.plot(data_labels, v[1:len(v)-1], label=v[0])
          ax.set_title(f'cluster{data_count}')
          ax.legend(bbox_to_anchor=(0, 1), loc='upper left', ncol=3, borderaxespad=0.5)
      else:
        break
      data_count += 1
  fig.savefig(f'{graph_title}.png')
```

## ○ 実行
> 2020/1/18 - 2021/11/18の間のデータを半年ごとに5つに分類して、各結果を画像として保存

```python
df, x_data, x_labels = data_get('2020/1/18', '2020/6/30')
cluster, df_cluster = k_means(df=df, x_data=x_data, n_clusters=5)
plot_view(cluster=cluster, df_cluster=df_cluster, graph_title='2020 01-06', x_labels=x_labels)

df, x_data, x_labels = data_get('2020/7/1', '2020/12/31')
cluster, df_cluster = k_means(df=df, x_data=x_data, n_clusters=5)
plot_view(cluster=cluster, df_cluster=df_cluster, graph_title='2020 07-12', x_labels=x_labels)

df, x_data, x_labels = data_get('2021/1/1', '2021/6/30')
cluster, df_cluster = k_means(df=df, x_data=x_data, n_clusters=5)
plot_view(cluster=cluster, df_cluster=df_cluster, graph_title='2021 01-06', x_labels=x_labels)

df, x_data, x_labels = data_get('2021/7/1', '2021/11/18')
cluster, df_cluster = k_means(df=df, x_data=x_data, n_clusters=5)
plot_view(cluster=cluster, df_cluster=df_cluster, graph_title='2021 07-', x_labels=x_labels)
```

## ○ 結果
### ➀第1波 4-5月
![2020 01-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184925/35875a2c-f00b-05ae-f662-49ab3d4b2fbf.png)

### ➁第2波 8月
![2020 07-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184925/01615a55-168b-94cf-c04d-b258b9dc1bf3.png)

### ➂第3波 1月・第4波 4-5月
![2021 01-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184925/8ce4895e-3b6f-5994-d796-82036a6b3ea5.png)

### ➃第5波 8-9月
![2021 07-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184925/598a7fba-0910-47ba-c927-c56c72fc384f.png)

### 結果から考察
- 東京・北海道・大阪・沖縄の4つの都道府県は、他の都道府県に比べて少し特殊な分類になることが多い。
- 2021～ 1都3県が同じクラスタに分かれている。足並みをそろえた結果か？
- ➂の分類結果が顕著だが、比較的近い地域でクラスタ分類されている。（cluster0が関東・cluster3が関西）
- ➂の分類から、  
　cluster0（関東）は第3波＞第4波  
　cluster4（関西）は第3波＜第4波  
 となっていて、cluster4グループに比べてcluster0グループは、第4波の感染者の増減を抑えられている。
- 最近に近づくにつれて、グループごとの波の特色がなくなってきている。 

## ○ 参考
> https://www.youtube.com/watch?v=okpRV08-svw
> https://qiita.com/HidKamiya/items/c3cc11438d1f67f655cb  

## ○ データの利用
「新型コロナ関連の情報提供:NHK」
> https://www3.nhk.or.jp/news/special/coronavirus/data/