競馬データの分析の目的は、競走馬の能力を適切に把握すること。そのための1つの方法として馬の能力の指数化、いわゆる、スピード指数化というものがあります。日本では西田式スピード指数が有名ですが、距離指数、馬場指数等、さまざまな補正がなされています。「さまざまな補正」に自分の考え方を盛り込みたい、という人はどうしても自分で指数を作る必要があります。この記事では、僕なりの考えで指数を作っていく過程をまとめています。
スピード指数とは
Wikepediaによると
「スピード指数(スピードしすう、Speed Figure)とは、主に競馬において競走馬の能力を、またはあるレースでのパフォーマンスを、数値で表すことを目的に開発された指数のこと。」(Wikipedia)と書かれています。
能力、パフォーマンスを数値で表せれば、競馬の予想において、比較が簡単になります。馬の能力を測るネタの基本は走破タイムです。競馬新聞を見れば、各馬の過去の戦績が載っていますが、過去の走破タイムを比べるにしても、馬ごとに走った競馬場も違えば、距離も違います。さらに、その日の馬場状態も違いますし、背負っていた斤量も。
これを同じ土俵で比べて比較できるようにするというのが、スピード指数の目的です。
スピード指数は、アンドリュー・ベイヤーによって提唱されたものが、元祖と言われており、日本では、西田式スピード指数と呼ばれる指数が有名です。
独自の指数を計算する
日本で最も有名な、西田式スピード指数の計算式は以下のようになっています。
スピード指数= (基準タイム-走破タイム)×距離指数+馬場指数+(斤量-55)×2+80
西田が100%正しいわけではありません。でも、上の式からは、以下のような点が参考になります。
・走破タイムをもとにする
・走破タイムは基準タイムとの差で評価する
・距離に応じて、補正する
・馬場に応じて、補正する
・斤量に応じて、補正する
僕がこれから作りたいと考えている指数は、以下の要素を考慮したものにしていきたいと考えています。
・走破タイム
・基準タイム・
・距離
・馬場
・斤量
・馬の成長傾向 ← これを考慮したい!というのが一番の目的です。
基準タイム作成の準備
世の中には、指数の計算方法は無数にあります。それでも、指数の理想から考えれば、走破タイムをもとに評価値を算出するはずです。しかし、その走破タイムは、競馬場・コースによって、価値が変わってきます。
(例)
芝2000m 良馬場の走破タイムの平均値
class | 中山 | 東京 |
2歳新馬 | 126.16 | 125.31 |
2歳未勝利 | 124.24 | 123.29 |
2歳1勝クラス | 121.96 | 122.68 |
2歳オープン | 122.90 | NA |
3歳新馬 | 126.76 | 127.09 |
3歳未勝利 | 123.68 | 122.95 |
3歳1勝クラス | 122.79 | 121.58 |
3歳オープン | 121.10 | 120.87 |
3歳以上1勝クラス | 122.24 | 121.25 |
3歳以上2勝クラス | 121.72 | 121.15 |
3歳以上3勝クラス | 120.66 | 120.27 |
3歳以上オープン | 120.76 | 119.40 |
4歳以上1勝クラス | 122.51 | 121.44 |
4歳以上2勝クラス | 121.84 | 121.21 |
4歳以上3勝クラス | 121.17 | 120.57 |
4歳以上オープン | 120.55 | 119.96 |
良馬場の芝2000mを2分00秒6で走ったとしても、中山であれば、4歳以上オープンのクラスの平均タイムとなりますが、東京だと1ランク下の4歳以上3勝クラスの平均走破タイム並みになってしまいます。
つまり、スピード指数を作るための第一歩は、走破タイムの価値を測れる「基準タイム」を作ること。
ここからは、過去のレースデータ(レースの条件、各馬の走破タイム等)を取得済みであることを前提に記事を描いていきます。
もし、過去のレースデータをお持ちでないなら、こちらの記事で、無料で過去のレースデータを入手する方法をまとめていますので、参考にしてください。
上の記事の方法で、レースデータを取得していれば、以下の表のようなレース情報(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歳新馬戦とするのもデータが安定性・信頼性から望ましくないと考えられ。。。
「各競馬場、距離、芝・ダート別、クラス別で単純に平均値をとって、基準タイムを作る」という案ではダメということか。。。
次回は、
「各競馬場、距離、芝・ダート別、クラス別で単純に平均値をとって、基準タイムを作る」という案ではダメだったので、次回、「統計モデルを作って、得られないデータは推定する」という方針で、基準タイムを作っていきます。