はじめに
警察庁から交通事故の詳細なデータがオープンデータとして公開されています。
このデータを色々こねてみて、最終的には交通事故発生予想みたいなことをしたい。
この記事では地図上に交通事故発生位置を表示するところまでをやります。
準備
ダウンロード
上記サイトからデータをcsvでダウンロードしておく。
とりあえず2023年だけ、補充票と高速票は今回は使いませんがダウンロードだけしておきます。
必要なライブラリのインストール
pandasとfoliumを入れます。
pip install pandas
pip install folium
データ読み込み
pandasで交通事故データを読み込みます。
頭のデータを表示してみて下図のように出てくればOK。
import pandas as pd
honhyo2023_path = "../data/2023/honhyo_2023.csv"
honhyo2023 = pd.read_csv(honhyo2023_path, encoding='cp932')
honhyo2023.head()
下処理
下処理しなきゃいけない部分が色々ありますが、今回はヒートマップで可視化するだけなので日時と緯度経度を修正します。
緯度経度の修正
元データの緯度経度は度分秒形式をつなげて記載しているので、度形式にします。
度分秒から度に変換する関数を定義
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"に代入
honhyo2023["lat"] = honhyo2023["地点 緯度(北緯)"].apply(degminsec2deg)
honhyo2023["lon"] = honhyo2023["地点 経度(東経)"].apply(degminsec2deg)
もとの列は不要なので削除してしまいます
honhyo2023.drop("地点 緯度(北緯)", axis=1)
honhyo2023.drop("地点 経度(東経)", axis=1)
日時の修正
元データは年月日時分が別の列で定義されていて不便なので、つなげてdatetime64変数とします。
honhyo2023.rename(columns={
'発生日時 年': 'Year',
'発生日時 月': 'Month',
'発生日時 日': 'Day',
'発生日時 時': 'Hour',
'発生日時 分': 'Minute'
}, inplace=True)
honhyo2023['datetime'] = pd.to_datetime(honhyo2023[['Year', 'Month', 'Day', 'Hour', 'Minute']])
元の日付データもいらないので消してしまいましょう。
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を使ってヒートマップ化してみます。
全事故現場の表示
まずは全ての事故現場の緯度経度を抽出
honhyo2023_all_latlon = honhyo2023.loc[:,["lat", "lon"]]
地図を定義してHeatMapレイヤを追加する
map = folium.Map(location=[35, 139], zoom_start=9, tiles='cartodbdark_matter')
HeatMap(honhyo2023_all_latlon, radius=7, blur=5).add_to(map)
地図を表示
map
さらにズームアップすると、事故が集中している場所がわかります。
時期を絞って表示
特定の時期、時間に発生した事故のみ表示できるようにします。
月ごとで表示
2023年の1月に発生した事故で絞ってみます。
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
全体と比べて量は減っていますがこれだけだと違いがよくわからないですね。
時間で表示
18時から20時の間に発生した事故で絞ってみます。
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
これもこれだけだと違いがよくわからないですね。さらなる分析が必要そうです。
終わりに
この記事では警察庁の交通事故オープンデータをヒートマップを使って可視化しました。
次は、より高度な可視化や下処理を行いたいと思います。