交通事故オープンデータを色々分析してみる１（ヒートマップ可視化編）

## はじめに
警察庁から交通事故の詳細なデータがオープンデータとして公開されています。

https://www.npa.go.jp/publications/statistics/koutsuu/opendata/index_opendata.html

このデータを色々こねてみて、最終的には交通事故発生予想みたいなことをしたい。
この記事では地図上に交通事故発生位置を表示するところまでをやります。

## 準備
### ダウンロード
上記サイトからデータをcsvでダウンロードしておく。
とりあえず2023年だけ、補充票と高速票は今回は使いませんがダウンロードだけしておきます。
### 必要なライブラリのインストール
pandasとfoliumを入れます。
```
pip install pandas
pip install folium
```

## データ読み込み
pandasで交通事故データを読み込みます。
頭のデータを表示してみて下図のように出てくればOK。
```python
import pandas as pd
honhyo2023_path = "../data/2023/honhyo_2023.csv"
honhyo2023 = pd.read_csv(honhyo2023_path, encoding='cp932') 
honhyo2023.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605106/0c9e010d-9f35-3838-c42b-5c4e5b88b278.png)

### 下処理
下処理しなきゃいけない部分が色々ありますが、今回はヒートマップで可視化するだけなので日時と緯度経度を修正します。

#### 緯度経度の修正
元データの緯度経度は度分秒形式をつなげて記載しているので、度形式にします。
度分秒から度に変換する関数を定義
```python
def degminsec2deg(degminsec):
    tmp_deg = int(degminsec / 10000000)
    tmp_min = int((degminsec % 10000000) / 100000)
    tmp_sec = degminsec % 100000 / 1000

    deg = tmp_deg + tmp_min / 60 + tmp_sec / 3600
    return deg
```

緯度経度の列をそれぞれ変換し新しく定義する列"lat"、"lon"に代入
```python
honhyo2023["lat"] = honhyo2023["地点　緯度（北緯）"].apply(degminsec2deg)
honhyo2023["lon"] = honhyo2023["地点　経度（東経）"].apply(degminsec2deg)
```
もとの列は不要なので削除してしまいます
```python
honhyo2023.drop("地点　緯度（北緯）", axis=1)
honhyo2023.drop("地点　経度（東経）", axis=1)
```

#### 日時の修正
元データは年月日時分が別の列で定義されていて不便なので、つなげてdatetime64変数とします。
```python
honhyo2023.rename(columns={
    '発生日時　　年': 'Year',
    '発生日時　　月': 'Month',
    '発生日時　　日': 'Day',
    '発生日時　　時': 'Hour',
    '発生日時　　分': 'Minute'
}, inplace=True)
honhyo2023['datetime'] = pd.to_datetime(honhyo2023[['Year', 'Month', 'Day', 'Hour', 'Minute']])
```

元の日付データもいらないので消してしまいましょう。
```python
honhyo2023.drop("Year", axis=1)
honhyo2023.drop("Month", axis=1)
honhyo2023.drop("Day", axis=1)
honhyo2023.drop("Hour", axis=1)
honhyo2023.drop("Minute", axis=1)
```

## ヒートマップ
交通事故の発生密度がわかるようにfoliumを使ってヒートマップ化してみます。

### 全事故現場の表示
まずは全ての事故現場の緯度経度を抽出
```python
honhyo2023_all_latlon = honhyo2023.loc[:,["lat", "lon"]]
```

地図を定義してHeatMapレイヤを追加する
```python
map = folium.Map(location=[35, 139], zoom_start=9, tiles='cartodbdark_matter')
HeatMap(honhyo2023_all_latlon, radius=7, blur=5).add_to(map)
```

地図を表示
```python
map
```

ヒートマップが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605106/971f8142-6e6e-243d-3bd5-fa220f698a50.png)

ズームアップすると都市部に集中しているのがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605106/0571f119-093d-f40d-7d47-76b4a1ab9d4c.png)

さらにズームアップすると、事故が集中している場所がわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605106/4be71f62-cc7d-ab3d-b245-a8b631e4fe52.png)

### 時期を絞って表示
特定の時期、時間に発生した事故のみ表示できるようにします。

#### 月ごとで表示
2023年の1月に発生した事故で絞ってみます。
```python
honhyo2023_jan = honhyo2023.query("datetime.dt.year == 2023 and datetime.dt.month == 1")
honhyo2023_jan = honhyo2023_jan.loc[:,["lat", "lon"]]

map = folium.Map(location=[35, 139], zoom_start=9, tiles='cartodbdark_matter')
HeatMap(honhyo2023_jan, radius=7, blur=5).add_to(map)
map
```
全体と比べて量は減っていますがこれだけだと違いがよくわからないですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605106/9dd91778-24d7-cd9c-d3ce-11eea2bea498.png)

#### 時間で表示
18時から20時の間に発生した事故で絞ってみます。
```python
honhyo2023_18_20 = honhyo2023.query("datetime.dt.hour >= 18 and datetime.dt.hour < 20")
honhyo2023_18_20 = honhyo2023_18_20.loc[:,["lat", "lon"]]

map = folium.Map(location=[35, 139], zoom_start=9, tiles='cartodbdark_matter')
HeatMap(honhyo2023_18_20, radius=7, blur=5).add_to(map)
map
```

これもこれだけだと違いがよくわからないですね。さらなる分析が必要そうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2605106/c396bdee-1224-1d61-0546-2884b20c3ec1.png)



## 終わりに
この記事では警察庁の交通事故オープンデータをヒートマップを使って可視化しました。
次は、より高度な可視化や下処理を行いたいと思います。