競馬スピード指数の作り方 〜 作成過程を公開(1)

データサイエンス

競馬データの分析の目的は、競走馬の能力を適切に把握すること。そのための1つの方法として馬の能力の指数化、いわゆる、スピード指数化というものがあります。日本では西田式スピード指数が有名ですが、距離指数、馬場指数等、さまざまな補正がなされています。「さまざまな補正」に自分の考え方を盛り込みたい、という人はどうしても自分で指数を作る必要があります。この記事では、僕なりの考えで指数を作っていく過程をまとめています。

スピード指数とは

Wikepediaによると
「スピード指数(スピードしすう、Speed Figure)とは、主に競馬において競走馬の能力を、またはあるレースでのパフォーマンスを、数値で表すことを目的に開発された指数のこと。」(Wikipedia)と書かれています。

能力、パフォーマンスを数値で表せれば、競馬の予想において、比較が簡単になります。馬の能力を測るネタの基本は走破タイムです。競馬新聞を見れば、各馬の過去の戦績が載っていますが、過去の走破タイムを比べるにしても、馬ごとに走った競馬場も違えば、距離も違います。さらに、その日の馬場状態も違いますし、背負っていた斤量も。

これを同じ土俵で比べて比較できるようにするというのが、スピード指数の目的です。

スピード指数は、アンドリュー・ベイヤーによって提唱されたものが、元祖と言われており、日本では、西田式スピード指数と呼ばれる指数が有名です。

独自の指数を計算する

日本で最も有名な、西田式スピード指数の計算式は以下のようになっています。

スピード指数= (基準タイム-走破タイム)×距離指数+馬場指数+(斤量-55)×2+80

西田が100%正しいわけではありません。でも、上の式からは、以下のような点が参考になります。

・走破タイムをもとにする
・走破タイムは基準タイムとの差で評価する
・距離に応じて、補正する
・馬場に応じて、補正する
・斤量に応じて、補正する

僕がこれから作りたいと考えている指数は、以下の要素を考慮したものにしていきたいと考えています。

・走破タイム
・基準タイム・
・距離
・馬場
・斤量
馬の成長傾向 ← これを考慮したい!というのが一番の目的です。

基準タイム作成の準備

世の中には、指数の計算方法は無数にあります。それでも、指数の理想から考えれば、走破タイムをもとに評価値を算出するはずです。しかし、その走破タイムは、競馬場・コースによって、価値が変わってきます。

(例)
芝2000m 良馬場の走破タイムの平均値

class中山東京
2歳新馬126.16125.31
2歳未勝利124.24123.29
2歳1勝クラス121.96122.68
2歳オープン122.90NA
3歳新馬126.76127.09
3歳未勝利123.68122.95
3歳1勝クラス122.79121.58
3歳オープン121.10120.87
3歳以上1勝クラス122.24121.25
3歳以上2勝クラス121.72121.15
3歳以上3勝クラス120.66120.27
3歳以上オープン120.76119.40
4歳以上1勝クラス122.51121.44
4歳以上2勝クラス121.84121.21
4歳以上3勝クラス121.17120.57
4歳以上オープン120.55119.96

良馬場の芝2000mを2分00秒6で走ったとしても、中山であれば、4歳以上オープンのクラスの平均タイムとなりますが、東京だと1ランク下の4歳以上3勝クラスの平均走破タイム並みになってしまいます。

 

つまり、スピード指数を作るための第一歩は、走破タイムの価値を測れる「基準タイム」を作ること。

ここからは、過去のレースデータ(レースの条件、各馬の走破タイム等)を取得済みであることを前提に記事を描いていきます。

もし、過去のレースデータをお持ちでないなら、こちらの記事で、無料で過去のレースデータを入手する方法をまとめていますので、参考にしてください。

競馬 過去データcsvをnetkeibaから無料で入手する方法
JRA-VANを無料で使えるのはお試し期間のみ。競馬のデータ分析を継続して行うには、どうしても過去の競馬レース結果データを自前で収集する必要があります。netkeibaからのスクレイピング方法やデータをcsv 形式で保存する方法について記述しています。

上の記事の方法で、レースデータを取得していれば、以下の表のようなレース情報(df.race.cond)と各馬の成績情報(df.race.record)が得られているはず。

レース情報

 

各馬の成績情報

 

 

レース情報には、競馬場、距離、芝・ダートの区別等が書かれていますが、各馬の成績情報は書かれていません。一方、成績情報には、走破タイムや斤量のデータが書かれていますが、競馬場、距離等のデータは書かれていません。両方のデータにはrace_idが含まれていますので、race_idをもとに両者を結合します。なお、今回作成するスピード指数は平地の競争のみを考えていますので、結合の際、事前に障害競走のデータは除いています。

 

library(tidyverse)

# 平地のレースのrace_id
race_ids <- df.race.cond %>%
filter(!str_detect(class1a, "障害")) %>%
select(race_id) %>%
unlist()

# 平地で着順がNA(=取り消し他)でないもの
df.base <- left_join(df.race.record, df.race.cond) %>%
filter(race_id %in% race_ids) %>% # 平地のrace_idのみ
filter(!is.na(着順)) # 着順がNAでないもののみ

 

さらに、必要なデータのみをまとめたdata.frameを作成します。

df.analysis <- df.base %>% 
select(race_id, date = 日付, place = 競馬場, class = class1a, Grace,
turf = 馬場, distance = 距離, LR = 左右, turf.cond = 馬場状態,
result = 着順, horseNo = 馬番, horseName = 馬名,
sex, age, burden = 斤量, record, last3F = 上り, odds = 単勝, weight)

まとめた結果がこちらになります。

 

基準タイムを作る

基準タイム作成の考え方もいくつかあると思いますが、ここでは、まず、良馬場、古馬(4歳以上)のデータについて、競馬場ごと、芝・ダートごと、距離ごと、クラスごとにデータをまとめて、その上で全馬の平均をとったものを求めたいと思います。

df.analysis %>% 
  filter(turf.cond == "良") %>%
  filter(str_detect(class, "4歳以上")) %>%
  group_by(place, turf, distance, class) %>%
summarise(base_time = mean(record), n = n()) %>% # base_time : 平均タイム
  arrange(place, turf, distance, class) %>%
  View()

Rなら簡単に平均タイムが計算できます。

。。。と思ったら、placeに「札幌」「函館」がない。

調べ見ると札幌、函館では古馬限定の(4歳以上の)レースがないんですね。3歳だと成長期だから、あまり混ぜたくないと思ってたんですけどね。仕方ない。3歳以上のレースで再整理してみる。

今度は札幌もきちんと入っている。上のスクリーンショットには載っていませんが、もう少し下に函館もありました。

次は、どのクラスを基準タイムのクラスにするかと眺めていると、問題が。。。

札幌では、2歳新馬のクラスの芝1000の競争が行われているのですが、3歳以上のクラスでは同条件の競争が行われていない。というより、もっと詳しく調べていると、札幌で芝1000mの競争は2歳新馬戦しかない。基準データなので、札幌だけ2歳新馬戦を使うわけにもいかず、また、全基準データを2歳新馬戦とするのもデータが安定性・信頼性から望ましくないと考えられ。。。

「各競馬場、距離、芝・ダート別、クラス別で単純に平均値をとって、基準タイムを作る」という案ではダメということか。。。

次回は、

「各競馬場、距離、芝・ダート別、クラス別で単純に平均値をとって、基準タイムを作る」という案ではダメだったので、次回、「統計モデルを作って、得られないデータは推定する」という方針で、基準タイムを作っていきます。

競馬スピード指数 当たる?当たらない?精度を知ってうまく活用
競馬をやっている人なら一度は「スピード指数」という言葉を聞いたことがありますよね。「当たる」という人もいれば、「当たらない」という人も。おそらく日本でもっとも有名なスピード指数である「西田式スピード指数」について精度、誤差を評価してみました。精度、誤差を知って上手に活用しましょう。
今週のメインレース の「血統指数」「タイム指数」「1着予想確率」
競馬予想に大切な要素である血統(父馬、母父馬)、過去の走破タイムを数値で評価。数値化することでこれまで競馬が上手い人にしかわからなかったこともクッキリ。