長野エンジニアライフ

東京から長野に移住したエンジニアのブログです。🦒🗻⛰

Pythonでオープンデータを活用する(1)〜数値化編〜

この記事は、 JSL (日本システム技研) Advent Calendar 2019 - Qiita 12/16の記事です。

オープンデータの情報は、文字情報が入っていたりと数値化されていない事が多い。そのため、特徴を探索するための数値計算ができなかったりと、プログラムが扱いやすいデータでない事が多い。

ということで、今回はPythonでオープンデータ数値化していく。 長野県自転車盗難データ

オープンデータを取得する

今回扱うオープンデータは、長野県自転車盗難データ。 https://www.pref.nagano.lg.jp/joho/kensei/tokei/johoka/opendata/www.pref.nagano.lg.jp

長野県オープンデータサイトにアクセスして、自転車盗難データを取得。赤枠内のデータが今回扱う自転車盗難データ。 自転車盗難データ ファイルの中身を確認してみると以下のように、盗難被害者ごとの特徴(年齢・職業etc)が列に指定されている。 列の確認 以下、自転車盗難データが持つ列。

  • 罪名
  • 手口
  • 管轄警察署
  • 管轄交番・駐車場
  • 市区町村コード
  • 都道府県
  • 市区町村
  • 町丁目
  • 発生年月日
  • 発生時
  • 発生場所の属性
  • 被害者の年齢
  • 被害者の職業
  • 施錠関係

以降、jupyter notebookを使用し数値化する。 qiita.com

オープンデータを読込む

自転車盗難データをそのまま読み込むとエラーが出る為、encoding="cp932"文字コードの指定が必要。

import pandas as pd
df = pd.read_csv("./CSV/nagano_2018zitensyatou.csv", encoding="cp932")
df.head()

【実行結果】 f:id:kawakeee:20191212001233p:plain

上記データの内、以下の列を数値化していく。また、列名が日本語のままだとコーディングしづらいので、列名を変更する。数値化対象外の列は不要のため削除する。

  • 発生年月日(始期)→ occurDate
  • 発生時(始期)→ occurTime
  • 被害者の年齢 → age
  • 被害者の職業 → occupation
  • 施錠関係 → isLock
# 列名変更
df = df.rename(columns={
    '発生年月日(始期)': 'occurDate',
    '発生時(始期)': 'occurTime',
    '被害者の年齢': 'age',
    '被害者の職業': 'occupation',
    '施錠関係': 'isLock',
})
# 列削除
del df['罪名']
del df['手口']
del df['管轄警察署(発生地)']
del df['管轄交番・駐在所(発生地)']
del df['市区町村コード(発生地)']
del df['都道府県(発生地)']
del df['市区町村(発生地)']
del df['町丁目(発生地)']
del df['発生場所の属性']
df.head()

【実行結果】 f:id:kawakeee:20191212002551p:plain だいぶすっきりした。

isLock(施錠状態)の数値化

isLockのカテゴリ値(施錠した/施錠せず)を確認後、以下のように数値化する。

  • 施錠した → 1
  • 施錠せず → 0
# isLock(施錠状態)の数値化
print("カテゴリ値の確認", df["isLock"].unique())
df["isLock"][df["isLock"] == "施錠した"] = 1
df["isLock"][df["isLock"] == "施錠せず"] = 0
# intに型変換
df["isLock"] = df["isLock"].astype(int)
# 数値化を確認
df.head()

【実行結果】  isLockの数値化

occupation(職業)の数値化

occupationのカテゴリ値を確認後、以下のように数値化する。

  • 小学生 → 0
  • 中学生 → 1
  • 高校生 → 2
  • 大学生 → 3
  • その他 → 4
  • 法人・団体、被害者なし → 5
# occupation(職業)の数値化
print("カテゴリ値の確認", df["occupation"].unique())
df["occupation"][df["occupation"] == "小学生"] = 0
df["occupation"][df["occupation"] == "中学生"] = 1
df["occupation"][df["occupation"] == "高校生"] = 2
df["occupation"][df["occupation"] == "大学生"] = 3
df["occupation"][df["occupation"] == "その他"] = 4
df["occupation"][df["occupation"] == "法人・団体、被害者なし"] = 5
# int型に型変換
df["occupation"] = df["occupation"].astype(int)
# 数値化を確認
df.head()

【実行結果】 ocupationの数値化

age(年齢)の数値化

ageのカテゴリ値を確認後、以下のように数値化する。

  • 10歳未満 → 10
  • 10歳代 → 10
  • 20歳代 → 20
  • 30歳代 → 30
  • 40歳代 → 40
  • 50歳代 → 50
  • 60-64歳 → 60
  • 65-69歳 → 60
  • 70歳以上 → 70

10歳未満10歳代10に、60-64歳65-69歳60に統一している点に注意。また、以下の観点から年齢が「法人・団体、被害者なし」となっている行を削除する。

  • 年齢の値としてふさわしくない
  • 1496件中7件しか存在しない

これにより、職業が法人・団体、被害者なし(occupation = 5)の行も存在しなくなる。

# age(年齢)の数値化
print("カテゴリ値の確認", df["age"].unique())
df["age"][df["age"] == "10歳未満"] = 10
df["age"][df["age"] == "10歳代"] = 10
df["age"][df["age"] == "20歳代"] = 20
df["age"][df["age"] == "30歳代"] = 30
df["age"][df["age"] == "40歳代"] = 40
df["age"][df["age"] == "50歳代"] = 50
df["age"][df["age"] == "60-64歳"] = 60
df["age"][df["age"] == "65-69歳"] = 60
df["age"][df["age"] == "70歳以上"] = 70
# age = 法人・団体、被害者なし の行を削除
df = df[df["age"] != "法人・団体、被害者なし"]
# int型に型変換
df["age"] = df["age"].astype(int)
# 数値化を確認
df.head()

【実行結果】

occurTime(発生時)の数値化

occurTimeのカテゴリ値を確認。occurTimeが不明と登録されている行を削除する。(中央値で穴埋めしても良いが、今回は削除)

# occurTime(発生時)の数値化
print("カテゴリ値の確認", df["occurTime"].unique())
# "不明"なデータは削除
df = df[df["occurTime"] != "不明"]
# int型に型変換
df['occurTime'] = df['occurTime'].astype(int)
# 数値化を確認
df.head()

【実行結果】 occuerTimeの数値化

occurDate(発生年月日)の数値化

occurDate(発生年月日)から月情報のみを抽出し、occurMonthの列を結合する。
以下の観点から、年・日の情報は数値化しない。

  • 2018/2017の年しか存在しない
  • によって日数が異なる
  • で盗難件数を比較したときに特徴が無さそう

また、occurDateは情報の抽出・数値化を完了し用済みのため削除する

# occurDate(発生年月日)の数値化
print("カテゴリ値の確認", df["occurDate"].unique())
# occurDateから occurMonth(発生月) を生成する
df['occurMonth'] =  list(map(lambda x: x[1] , df['occurDate'].str.split('/')))
# int型に型変換
df['occurMonth'] = df['occurMonth'].astype(int)
# occurDateの削除
del df['occurDate']
# 数値化されている事を確認
df.head()

【実行結果】 occurMonthの列追加

データの出力

最後に、型も数値化されていることを確認しCSVに出力する。

# 型も数値型であることを確認
print(df.dtypes)
# 数値化したデータをcsv出力
df.to_csv('./CSV/output/transform_bohan_data.csv')

以下、数値変換完了したデータ。
数値変換後のデータ

ソースコード

github.com (githubのnotebookが見れない場合はこちら)