python初学者が競馬予測をしてみたpart1(データの前処理編)

皆さん初めまして、KHnodeと申します。

今回が初めての投稿でありますが、さっそく書いていきたいと思います。

今回のテーマは「python初学者が競馬予測をしてみた」です。
 
筆者自身は競馬が好きなのですが、中々当たらないので機械に予測させようと考え機械学習で有名なpythonの勉強を始めました。

ですので、間違っているところやめんどくさいコーディングをしているところは多々ありますが、その際はご指摘をいただけると幸いです。

 
##################################################################

 

使用するデータについて

使用するデータはJRA-VANから出ている TARGETを使用しています。
(本当はスクレイピングをしたかったのですが、勉強量が増えるとパンクしてしまいそうだったので今回は諦めました次回は挑戦したいです。)
jra-van.jp

データの中身はこんな感じ、

日付 芝ダ 距離 馬場状態 騎手 父馬名 母父馬名 馬番 年齢 性別 人気 オッズ 確定順位
2011.1.22 1000 野元昭嘉 ヴィクトリースピーチ ティッカネン 1 3 9 112.4 8


他にも前走結果や、坂路調教のタイムなど様々なデータがありますがTARGETの取り方がよくわからなかったので入れていません。

 

データの前処理

欠損値をdropnaで落とします。

import pandas as pd

 df = pd.read_excel('main.xlsx')
 df = df.dropna(how='any')

後、特徴量の生成も行いました。

df['オッズ比'] = (df['オッズ'] // df['人気']) ** 2

本当はグラフなどで関係性を見つけてから特徴量を作成していくと思うのですが、長年の感で作成しました

次に、馬場状態や騎手といった文字列が入っているところを処理していきます。
本当はダミー変数化して行きたかったのですが、それをしてしまうと何万列となってしまい、処理が大変になるだろうと思いましたので「カテゴリ変数」をつかって処理していきます。  

import category_encoders as ce

category_data = ['芝ダ', '距離', '馬場状態',
          '騎手', '父馬名', '母父馬名', '性別']
    ce_oe = ce.OrdinalEncoder(cols=category_data, handle_unknown='impute')
    df = ce_oe.fit_transform(df)

    for i in category_data:
        df[i] = df[i] - 1

    for i in category_data:
        df[i] = df[i].astype('category')

forループが2つも重なって変なコードになっていますが、合わせてしまうと何故かうまくいかなかったので分けています。
もしわかる人がいらっしゃいましたらご教授いただければ幸いです。
astypeの所はカテゴリー型にしていますが、int型でもできるらしいです。

最後に目的変数ですが、3着以内きたことがある馬にフラグを立て1-0に直したものとしました。

d_ranking = lambda x: 1 if x in [1, 2, 3] else 0
df['フラグ'] = df['確定順位'].map(d_ranking)

いろいろと調べた結果このコードが簡単にかけそうだったので書いてみました。
lambdaを初めて使ったのですが、思いのほか使いやすいのでお勧めです。

以上前処理編は終わりにします。
次はモデルを組んで予想していきたいと思います。

追記~~(2020/2/20)
特徴量を設定し、予測すると1番2番人気だけくると予想したので外しています。
詳しい内容は次のブログにて紹介します。