集計表とグラフ、HeatMapの作成

#はじめに
広島県警のオープンデータを用いてデータサイエンスの実習を行いました。

このデータを処理するにあたって行ってきた手法とどんな結果が得られたか紹介していきます。

オープンデータから集計表とグラフ、HeatMapを作成するヒントになればいいと思っています。


###動作環境
- **OSX**
- **pyenv Python3.6.5**
- **Jupyter 1.0.0**
- **Pandas 0.23.0**
- **Numpy 1.14.3**
- **matplotlib 2.2.2**
- **seaborn 0.8.1**
- **geopy 1.20.0**
- **folium 0.10.0**


###参考サイト

 https://www.pref.hiroshima.lg.jp/site/police/list426-1967.html

上のURLからデータを取得して、以下のようなPandasやNumpyで集計と分析を行い、その集計表をmatplotlibを使いグラフ化したりします。

<img width="373" alt="時間帯ごとの犯罪件数.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607323/93005acb-e9f1-f87f-e4d2-18cea6981d66.png">

<img width="373" alt="時間帯ごとの犯罪件数折れ線グラフ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607323/f1fbff79-6b4b-18b5-60fa-8eb48fb20989.png">

以下のようなHeatMapを生成するところまでを紹介します。

<img width="600" alt="heatmap.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607323/5c612640-9f8b-bdf5-c90c-a0a3b871b198.png">


2018年度版のデータはこのようになってます。
<img width="600" alt="ヘッダー.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607323/777e43c1-45d9-200f-eda3-276b08020ef8.png">



#コード作成
csvデータは複数ある場合はglobを使い読み込んでいきます。globは引数に指定されたパターンにマッチするものを取得できます。これによりコードの量を減らせます。


```ruby:test.py
# 分析ファイルフォルダ：広島, ファイル拡張子：csv

files = glob.glob("./都道府県/広島/*.csv")

res_hirosima = None

for file in files:

    tmp = pd.read_csv(file, encoding="SHIFT-JIS") #csvファイルの読み込み

    if res_hirosima is None:

        res_hirosima = tmp

    else:

        res_hirosima= res_hirosima.append(tmp, sort=True)

        
# res_hirosimaとzyusyo_csvを”住所”で連結

res_hirosima_zyusyo = pd.merge(res_hirosima, zyusyo_csv, on = "住所", how="outer")
```


HeatMapの作成のためには座標情報（経度・緯度）とマップが必要になります。

そこでGoogle Map Platformで経度緯度情報を取得し、geopy経由でGoogleMapに表示します。

経度・緯度を取得するためには時間とお金がかかるため、後でこのデータをcsvファイルを作成します。

経度・緯度を取得するためには都道府県・市町村・町丁目の項目の文字列を足し合わせます。Google Maps Platformの仕様上細かい住所情報が必要なためです。そして新たに「住所」というcolumnsを作成したDataFrameにconcatメソッドを用いて連結しいていきます。

```
res_hirosima["住所"] = res_hirosima['都道府県（発生地）'] + res_hirosima['市区町村（発生地）'] + res_hirosima["町丁目（発生地）"]

# res_hirosimaとzyusyo_csvを”住所”で連結

res_hirosima_zyusyo = pd.merge(res_hirosima, zyusyo_csv, on = "住所", how="outer")
```

作成したデータをcsvファイルに出力し、to_csv_out1.csvとします。

HeatMapの作成はこのcsvファイルを使用します。

 

Pandasとnumpyとmatplotlibを使い集計を行いグラフで作成します。

”発生時（時期）”と”発生件数”のDataFrameを作ります。

発生時（時期）に”不明”という要素が含まれていることがわかったので全てNa Nに変換します。

変換した後dropnaで全て削除します。

また、発生時（始期）の要素をto_numericを用いてfloat型に変換します。

```
#res_hirosima_zyusyo["発生時(始期)"]にある要素"不明"をNaNに変換

res_hirosima_zyusyo.loc[res_hirosima_zyusyo["発生時（始期）"] == "不明", "発生時（始期）"] = None

res_hirosima_zyusyo["発生件数"] = 1

# 数値のみの行に変換

res_hirosima_zyusyo['発生時（始期）'] = pd.to_numeric( res_hirosima_zyusyo['発生時（始期）'] )

# res_hirosima_zyusyoにあるNaNの除去

time = res_hirosima_zyusyo.loc[:, ["発生時（始期）", "発生件数"]].dropna()

#犯罪の多い時間帯をグラフで表示するためにres_hirosima_zyusyoを加工

#変数：time

time.head(5)
```

#Groupyを使い時間帯ごとの発生件数

```
grouped = time["発生件数"].groupby(time["発生時（始期）"])

#変数：time

#時刻に対する合計発生件数を表示

time = grouped.sum()
```

Matplotlibを用いグラフを出力します。

この時、x軸にメモリが表示されていないのでxticksを使い０〜２３まで表示します。


```
#どの時間帯に犯罪が多いか調べるためグラフで表示

time.plot()

plt.xticks(np.arange(0, 24, 1))
```

<img width="373" alt="20191125062023.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607323/b0cce4f6-c6bd-7383-6afa-876a258cd421.png">

月ごとの犯罪種類の比較をpivot_tableを用いて集計します。pivot_tableはカテゴリごとにグルーピングして量的データの統計量の確認が便利だからです。

res_hirosima_zyusyoから必要な情報（手口・発生件数・発生月）を取り出します。

それを月ごとの種類別発生件数をグラフで表示します。

```
#res_hirosima_zyusyoを加工

month = res_hirosima_zyusyo.loc[:, ["手口", "発生月", "発生件数"]]

month.head(5)

#変数：month

#一月あたりの手口別比率

month = pd.pivot_table(month, values="発生件数",index="発生月",  columns="手口", aggfunc="sum")
#NaNを０に変換

month =month.fillna(0)

month.plot.bar(stacked=True, alpha=0.5)
```

<img width="373" alt="20191125062032.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607323/64ebc540-78e2-bc21-b4cb-643740be2f86.png">


#HeatMap作成
HeatMap作成のためにlocを使いres_hirosima_zyusyoから"latitude"と"longitude"を取り出します。

longitudegは地図上喉この情報を追加するのかをs指定に使います。

HeatMapに情報を追加するにはDataFrameではなくlistである必要があるのでvalues.tolist()を使いlist化します。


```
#分析ファイルのフォルダ：lat_lon, ファイル拡張子: csv

#lat_lon.csvの内容: 犯罪が発生した場所に対する経度と緯度



#lat_lon = pd.read_csv("lat_lon.csv")



lat_lon = res_hirosima_zyusyo.loc[:, ["latitude", "longitude"]]

# メソッドを用いてDataFrameをlistに変換

lat_lon = pd.DataFrame(lat_lon.loc[:, ["latitude", "longitude"]]).values.tolist()
```


以下のようなコードでプロットしていきます。

locationで表示位置を決め、tileを指定、zoom_startでどのくらい全体を見るか決めます。

そしてlistにある経度緯度情報をもとにHeatMapに情報を追加していきます。


```
m = folium.Map(

    location=[34.4,132.5],

    tiles='OpenStreetMap',

    zoom_start=12)

list = lat_lon_7

HeatMap(list, radius=10, blur=3).add_to(m)
```

<img width="600" alt="20191129125106.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607323/e8af3fd0-79dc-08f5-cfa3-aa799e7da288.png">


上記のような結果となりました。