さて、皆さんは機械学習で重要なものって何があると思いますか? 実行するコードの質や、その中で使うパッケージ、実行するマシンのスペックも大きく結果に影響してくるでしょう。 しかしそれらすべてを手に入れられる最高のものを用意したとしても、やりたいことに関するデータセットがなければ何もできないのです!
それでは機械学習で使うデータをどうやって手に入れればいいのでしょうか? まず第一に様々な企業や研究者などがデータセットを公開してくれているものがあります。これらは機械学習のために作られたものなので、扱いやすく信頼性もある程度高いと思います。しかし公開されているデータの中に自分が使いたいものがあるとは限りません。もしほしいデータがなかったらどうすればいいのか。
自分で作ればいいのです。 そもそも近年ディープラーニングが隆盛してきた理由はマシン性能の向上と、インターネットの普及による大量のデータ入手が可能になったからでした。 インターネット上には膨大な量のさまざまな情報があふれており、これを活用しない手はありません。
さて今回どんなデータセットを作るのかというと、電車の遅延と気象条件の組み合わせた物にしようと思います。 気象情報を説明変数にして、電車が遅延するかを目的変数にするイメージです。 気象情報のデータは気象庁から入手できるのですが、電車の遅延情報をまとめたデータは公開されていないようです。(企業主催のコンペなどで特別に公開されたりはしていたようですが。) というわけで今回は鉄道会社の公式ツイッターからデータを作ることにします。 twitter.com 今回東急電鉄さんのツイートを利用させてもらいます。
環境について
使用言語
・python3系
使用パッケージ(インストールが必要なもの)
・pandas:DataFrameを使うため
・requests_oauthlib:ツイッターの認証のため
本題
気象データ
まず、気象庁から過去の気象情報をダウンロードします。 気象庁|過去の気象データ・ダウンロード 地点は東京、時別値で項目は降水量、現地気圧、相対湿度を選んでみました。 ここが厄介なのですが、ここで一度にダウンロードできるデータ量が制限されており、この三つの項目を選ぶと5か月分くらいしか取得できません。
なので期間をずらして必要な分だけ取得しましょう。今回は2016/4/30~2017/7/28(3回分)取得してみました。 まずは気象データのほうを成型していきます。 どんなデータ形式になってるかとりあえず見てみましょう。
import pandas as pd
import codecs
with codecs.open("data0.csv", "r", "Shift-JIS", "ignore") as file:
df =pd.read_table(file, delimiter=",")
df
列の名前がUnnamed:1…となっているのでこれを使って要らない列を削除していきます。降水に関しては量が0でも、現象無し情報が0の行があるので、現象無し情報の方を降水の情報として用います。湿度や気圧に関しては品質情報や均質番号はいらないので消します。
さらに列名がわかりづらいので上4行を消して新しい列名を付けます。 これらの作業を各ファイルから読み取ったDataFrameに行い、最後に一つのDataFrameにまとめます。 最後に日時のデータを参照しやすいように単純な数字に変換しておきます。 これで気象情報の方は完成です。
import codecs
def YmdHMS2(d_time):
n_time = time.strptime(d_time, '%Y/%m/%d %H:%M:%S')
return int(time.strftime("%Y%m%d%H%M%S", n_time))
a_df = []
list = [1,3,4,6,7,9,10]
for i in range(3):
with codecs.open("data{}.csv".format(i), "r", "Shift-JIS", "ignore") as file:
b_df =pd.read_table(file, delimiter=",")
b_df = b_df.drop([0,1,2,3])
for i in list:
b_df = b_df.drop(['Unnamed: {}'.format(i)],axis=1)
b_df.columns = ['time','rain','humidity','puressur']
b_df = b_df.reset_index(drop=True)
a_df.append(b_df)
df = pd.concat([a_df[2],a_df[1],a_df[0]], ignore_index=True)
for i in df.index:
df.time[i] = YmdHMS2(df.time[i])
df
遅延情報の取得
次にツイッターから遅延情報を取得していきましょう。 ツイッターからデータを取得する方法については以下のサイトを主に参考にしました。 TwitterAPI でツイートを大量に取得。サーバー側エラーも考慮(pythonで) | コード7区 指定の路線が遅延したかとその時間のデータを作ります。 アカウントのタイムラインを時系列順に取得し、特定の路線名と「遅れ」の文字が含まれていたツイートの時間に遅延があったと判断します。
from requests_oauthlib import OAuth1Session
import json
import datetime, time, sys, calendar
import pandas as pd
CK = '##############################'
CS = '##################################################'
AT = '##########################################################'
AS = '##################################################'
session = OAuth1Session(CK, CS, AT, AS)
max_id = 891290216417210368
res_text = []
N = 40
line = "東横線"
url = 'https://api.twitter.com/1.1/statuses/user_timeline.json'
def YmdHMS(created_at):
time_utc = time.strptime(created_at, '%a %b %d %H:%M:%S +0000 %Y')
unix_time = calendar.timegm(time_utc)
time_local = time.localtime(unix_time)
return int(time.strftime("%Y%m%d%H00", time_local))
for i in range(N):
res = session.get(url, params = {'user_id':1199983754, 'count':100, 'max_id':max_id})
res_text_semi = json.loads(res.text)
if res.status_code != 200:
print ("Twitter API Error: %d" % res.status_code)
sys.exit(1)
for tweet in res_text_semi:
if tweet['id'] < max_id:
max_id = tweet['id']
res_text.extend(res_text_semi)
df1 = pd.DataFrame(columns=["time","delay"])
for tweet in reversed(res_text):
if tweet['text'].find('遅れ') != -1 and tweet['text'].find(line) != -1:
delay = 1
else:
delay = 0
t_df = pd.DataFrame([[YmdHMS(tweet['created_at']),delay]],columns=["time","delay"])
df1 = df1.append(t_df,ignore_index = True)
df1 = df1.drop_duplicates(['time'])
df1
最後に気象データと遅延データを組み合わせます。 気象データは毎時の値がありますが、遅延データはそうではないので、気象データに遅延データをくっつけるようにします。 そしてその間の値は、一度遅延したら次に遅れのないツイートが来るまで遅延していたものとします。 そして最後にcsvファイルとして書き出します。
merged = pd.merge(df,df1,on='time',how='left')
flag = False
for i in merged.index:
if merged.delay[i] == 1:
flag = True
elif merged.delay[i] == 0:
flag = False
else:
if flag == True:
merged.delay[i] = 1
else:
merged.delay[i] = 0
merged.to_csv('delay_data.csv')
こうして無事電車の遅延情報と気象情報を合わせたデータセットができました。 次回はこのデータセットを使って実際に機械学習をやる予定です。