第1回目の記事は、環境設定とデータの取得まで終了
今回は、データの前処理(CSVデータの読み込みからデータの各種処理)をやってみるのだ
#開発環境
###Anaconda3 のインストール
#データの取得
###ターゲットフロンティアの出力データを使用
####ターゲットフロンティアのレース検索で CVS 出力
※前回はここまで終了-------------------------------
#データの前処理
###CVS の読込みについて
####20年分の全データを読み込んでみたら Wall time: 41.3 s
CSV ファイルの読み込みについては、pandas をインポートして簡単に成功
エンコードは、shift-jis でも大丈夫と書いてあるのだが、エラーが出るので encoding = 'cp932'
に修正(cp932 ってなんだ💦)
データ型も指定しないとエラーがでるので、とりあえず全てオブジェクト型で取り込み
(指定しないとこの後のマージができなかったので応急処置。よい処理方法あれば教えて下さい)
rd_2000all.csv
には 2000年からのレース検索で得られる全データを詰め込んで読み込んでみた
Wall time: 41.3 s
ターゲットフロンティアからの出力もかなりの時間を要したし、この出力データは使わないこととした
%%time
import pandas as pd
# csvデータ読込み
rd = pd.read_csv('rd_2000all.csv'
, encoding = 'cp932'
, dtype = 'object'
, skipinitialspace = True
)
Wall time: 41.3 s
rd.info()
RangeIndex: 1024923 entries, 0 to 1024922
Columns: 274 entries, M to ←
dtypes: object(274)
memory usage: 2.1+ GB
####20年分の使うかもしれないデータだけを読込み
rd2000all.csv
には 20000年からのレース検索で得られる全データを詰め込んで読み込んでみたが、やはり遅い
絶対に使わないデータだけを削除して rd2000.csv
を読み込んでみた
私の能力低い PC で 13秒
とりあえず、このデータで進めてみる
%%time
import pandas as pd
# csvデータ読込み
rd = pd.read_csv('rd2000.csv'
, encoding = 'cp932'
, dtype = 'object'
, skipinitialspace = True
)
Wall time: 13.3 s
rd.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1024923 entries, 0 to 1024922
Data columns (total 75 columns):
# Column Non-Null Count Dtype
(省略)
dtypes: object(75)
memory usage: 586.5+ MB
n 走前までのデータを連結
CSV で取り込んだデータは、カラム数が 75個
今回は出走馬の実力を測る特徴量として、
予想するレースでは、斤量のみ
n 走前のレースでは 斤量・単勝オッズ・人気・補正(補正タイム:クラス内相対値)・補9(補正タイム:絶対値)、確定順位 を使用した
※予想するレースの人気やオッズを入れると人気馬ばかりの予想結果になるので、予想するレースの特徴量は 斤量 のみとした。今後は、馬特有データの血統などは特徴量として扱いたい
レースID | 各データ | 前走ID |
---|---|---|
ID01 | *** | ID10 |
ID02 | *** | ID11 |
ID10 | *** | ID20 |
ID11 | *** | ID21 |
ID20 | *** | ID30 |
ID21 | *** | ID31 |
とりあえず、今のデータフレーム(↑)は 1 レース分の各データが入っているので、それをレースID と前走ID をマージして n 走前までのデータが連結したデータフレーム(↓)に加工してみた。
この部分については参考になるコードが見つからなかったので python 初心者らしい!?力技で解決したのだ。
※もっとスマートなコードの書き方教えて下さい
レースID | 予想レースデータ | 前走ID | 1走前データ | 前々走ID | 2走前データ | 3走前ID |
---|---|---|---|---|---|---|
ID01 | *** | ID10 | *** | ID20 | *** | ID30 |
ID02 | *** | ID11 | *** | ID21 | *** | ID31 |
ID10 | *** | ID20 | *** | ID30 | ||
ID11 | *** | ID21 | *** | ID31 | ||
ID20 | *** | ID30 | ||||
ID21 | *** | ID31 |
欠損地処理、データ型処理、目的変数の処理
その後、欠損値処理、データ型処理、目的変数の処理を行った
目的変数は、出走馬の着順を 3着以内なら 1、4着以下なら 0 に変更した
# カラム抽出 使用するカラムを抽出
rd = rd[['レースID(新)', '斤量', '単勝オッズ', '人気', '補正', '補9', '確定着順', '前走レースID(新)']]
# 斤量のマークを外す
rd['斤量'] = rd['斤量'].str.extract('(\d+)', expand=False)
# 過去レース用 rd_pr にコピー
rd_pr = rd.copy()
# rdは、直近レースデータ用+目的変数 ID、斤量、確定着順
rd = rd.drop(['単勝オッズ', '人気', '補正', '補9'], axis=1)
# n走前まで連結(もっとスマートなコードの書き方教えてください)
n = 1
rd_pr_cn = rd_pr.columns
for i in range(n): # もっとスマートなコードの書き方教えてください
rd_pr.columns = rd_pr_cn
rd_pr = rd_pr.rename(columns=lambda s: str(i+1) + '_' + s)
rd_pr = rd_pr.rename(columns={str(i+1)+'_レースID(新)': '前走レースID(新)'})
rd = pd.merge(rd, rd_pr, on = '前走レースID(新)', how='left')
rd.drop([ '前走レースID(新)'], axis=1, inplace=True)
rd = rd.rename(columns={str(i+1)+'_前走レースID(新)': '前走レースID(新)'})
rd.drop(['レースID(新)', '前走レースID(新)'], axis=1, inplace=True)
# 欠損値があるレコードは除去
rd.dropna(how='any', inplace=True)
# データフレーム全体の型を変更
rd = rd.astype(float)
# 着順が3着以内かどうかのカラムを追加する
f_ranking = lambda x: 1 if x in [1, 2, 3] else 0
rd['3着以内'] = rd['確定着順'].map(f_ranking)
rd.drop(['確定着順'], axis=1, inplace=True)