PR

ロードマップ5: 24年分の競馬データを使って血統分析part1

Python
この記事は約64分で読めます。
スポンサーリンク
スポンサーリンク

0.下準備¶

In [2]:
import pandas as pd
import warnings
import sys
sys.path.append("..")
from src.core.db.controller import execSQL, getTableList, getDataFrame
import numpy as np
import pathlib
from src.data_manager.preprocess_tools import DataPreProcessor
from src.data_manager.data_loader import DataLoader
import matplotlib.pyplot as plt
import japanize_matplotlib
import re
from wordcloud import WordCloud
import random

warnings.filterwarnings("ignore")

データベースからデータの読み込み

In [5]:
root = pathlib.Path(".").absolute().parent
dbpath = root / "data" / "keibadata.db"
dbpath
Out[5]:
WindowsPath('e:/work_umaai/0001/dev-um-ai-1-analysis-horseblood/data/keibadata.db')
In [6]:
# 血統情報のテーブル一覧をDBから取得する
horseblood_list = [tbl for tbl in getTableList(dbpath) if "horseblood" in tbl]
horseblood_list.sort(key=lambda x: int(x[-4:]))
horseblood_list
Out[6]:
['horseblood1986',
 'horseblood1987',
 'horseblood1988',
 'horseblood1989',
 'horseblood1990',
 'horseblood1991',
 'horseblood1992',
 'horseblood1993',
 'horseblood1994',
 'horseblood1995',
 'horseblood1996',
 'horseblood1997',
 'horseblood1998',
 'horseblood1999',
 'horseblood2000',
 'horseblood2001',
 'horseblood2002',
 'horseblood2003',
 'horseblood2004',
 'horseblood2005',
 'horseblood2006',
 'horseblood2007',
 'horseblood2008',
 'horseblood2009',
 'horseblood2010',
 'horseblood2011',
 'horseblood2012',
 'horseblood2013',
 'horseblood2014',
 'horseblood2015',
 'horseblood2016',
 'horseblood2017',
 'horseblood2018',
 'horseblood2019',
 'horseblood2020',
 'horseblood2021']

血統情報のテーブル情報を取得する

In [7]:
dfblood = pd.concat([
    getDataFrame(tablename, dbpath) for tablename in horseblood_list
], ignore_index=True)
dfblood
Out[7]:
horseId gen1 gen2 gen3 gen4 gen5 gen1ID gen2ID gen3ID gen4ID gen5ID
0 1986102130 ジュニアス\nJunius(米)\n Raja Baba\n\n Bold Ruler\n\n Nasrullah Nearco 000a0001af 000a0010fa 000a000e94 000a000f88 000a000f8b
1 1986102130 ジュニアス\nJunius(米)\n Raja Baba\n\n Bold Ruler\n\n Nasrullah Mumtaz Begum 000a0001af 000a0010fa 000a000e94 000a000f88 000a007851
2 1986102130 ジュニアス\nJunius(米)\n Raja Baba\n\n Bold Ruler\n\n Miss Disco Discovery 000a0001af 000a0010fa 000a000e94 000a00780d 000a0013fd
3 1986102130 ジュニアス\nJunius(米)\n Raja Baba\n\n Bold Ruler\n\n Miss Disco Outdone 000a0001af 000a0010fa 000a000e94 000a00780d 000a0078d1
4 1986102130 ジュニアス\nJunius(米)\n Raja Baba\n\n Missy Baba\n\n My Babu Djebel 000a0001af 000a0010fa 000a007cd4 000a000f85 000a000ede
3727867 2021105244 マンハッタンセレブ\n\n サトルチェンジ\nSubtle Change(愛)\n Law Society\n\n Bold Bikini Ran-Tan 2003102531 000a000334 000a0016ec 000a0083ad 000a0083ac
3727868 2021105244 マンハッタンセレブ\n\n サトルチェンジ\nSubtle Change(愛)\n Santa Luciana\n\n Luciano Henry the Seventh 2003102531 000a000334 000a0002d8 000a001347 000a000e22
3727869 2021105244 マンハッタンセレブ\n\n サトルチェンジ\nSubtle Change(愛)\n Santa Luciana\n\n Luciano Light Arctic 2003102531 000a000334 000a0002d8 000a001347 000a00838d
3727870 2021105244 マンハッタンセレブ\n\n サトルチェンジ\nSubtle Change(愛)\n Santa Luciana\n\n Suleika Ticino 2003102531 000a000334 000a0002d8 000a00807e 000a001239
3727871 2021105244 マンハッタンセレブ\n\n サトルチェンジ\nSubtle Change(愛)\n Santa Luciana\n\n Suleika Schwarzblaurot 2003102531 000a000334 000a0002d8 000a00807e 000a00807f

3727872 rows × 11 columns

2000年から2023年分の出走情報も取得する

In [10]:
from src.data_manager.data_loader import DataLoader
In [11]:
start_year = 2000
end_year = 2023

data_loader = DataLoader(start_year, end_year, dbpath)
dataPreP = DataPreProcessor()
df = data_loader.load_racedata()
df
2024-07-15 11:44:54.972 | INFO     | src.data_manager.data_loader:load_racedata:23 - Get Year Range: 2000 -> 2023.
2024-07-15 11:44:54.973 | INFO     | src.data_manager.data_loader:load_racedata:24 - Loading Race Info ...
2024-07-15 11:44:56.945 | INFO     | src.data_manager.data_loader:load_racedata:26 - Loading Race Data ...
2024-07-15 11:45:14.912 | INFO     | src.data_manager.data_loader:load_racedata:28 - Merging Race Info and Race Data ...
Out[11]:
raceId place raceName raceDetail raceDate startTime distance weather field condition jockey jockeyId time passLabel last3F weight gl teacher teacherId boss
0 200006010101 中山 4歳未勝利 4歳未勝利 2000-01-05 10:00 1000 吉田豊 00733 62.1 3-4 38.5 446 -6 [東]\n嶋田功 00393 永嶋道治
1 200006010101 中山 4歳未勝利 4歳未勝利 2000-01-05 10:00 1000 中舘英二 00635 60.5 2-1 37.4 428 -4 [東]\n池上昌弘 00390 ユーワ
2 200006010101 中山 4歳未勝利 4歳未勝利 2000-01-05 10:00 1000 宗像徹 00725 62.3 6-8 38.5 452 -10 [東]\n矢野進 00325 山田順通
3 200006010101 中山 4歳未勝利 4歳未勝利 2000-01-05 10:00 1000 菊沢隆徳 00672 61.4 8-7 37.3 462 0 [東]\n小桧山悟 01005 柴原榮
4 200006010101 中山 4歳未勝利 4歳未勝利 2000-01-05 10:00 1000 田面木博 00621 61.5 3-4 38.0 414 4 [東]\n高松邦男 00219 吉野吉晴
1173140 202309050912 阪神 カウントダウンS 3歳以上3勝クラス 2023-12-28 16:05 1200 横山典弘 00660 68.9 14-14 33.3 476 2 [西]\n鈴木孝志 01111 林千枝子
1173141 202309050912 阪神 カウントダウンS 3歳以上3勝クラス 2023-12-28 16:05 1200 角田大和 01186 69.2 5-8 34.1 472 8 [西]\n佐々木晶 00429 岡浩二
1173142 202309050912 阪神 カウントダウンS 3歳以上3勝クラス 2023-12-28 16:05 1200 菱田裕二 01144 70.4 16-15 34.4 490 14 [西]\n飯田雄三 01050 竹園正繼
1173143 202309050912 阪神 カウントダウンS 3歳以上3勝クラス 2023-12-28 16:05 1200 藤懸貴志 01138 69.5 9-11 34.2 498 10 [西]\n寺島良 01158 日隈良江
1173144 202309050912 阪神 カウントダウンS 3歳以上3勝クラス 2023-12-28 16:05 1200 荻野琢真 01112 69.8 5-4 34.9 472 -4 [東]\n石毛善彦 00428 ミルファーム

1173145 rows × 36 columns

読み込んだ出走情報から、前処理を行う

In [12]:
df = dataPreP.exec_pipeline(df)
2024-07-15 11:46:00.265 | INFO     | src.data_manager.preprocess_tools:__0_check_use_save_checkpoints:34 - Start PreProcess #0 ...
2024-07-15 11:46:00.267 | INFO     | src.data_manager.preprocess_tools:__1_exec_all_sub_prep1:37 - Start PreProcess #1 ...
2024-07-15 11:46:06.837 | INFO     | src.data_manager.preprocess_tools:__2_exec_all_sub_prep2:39 - Start PreProcess #2 ...
2024-07-15 11:46:20.417 | INFO     | src.data_manager.preprocess_tools:__3_convert_type_str_to_number:41 - Start PreProcess #3 ...
2024-07-15 11:46:24.202 | INFO     | src.data_manager.preprocess_tools:__4_drop_or_fillin_none_data:43 - Start PreProcess #4 ...
2024-07-15 11:46:27.916 | INFO     | src.data_manager.preprocess_tools:__5_exec_all_sub_prep5:45 - Start PreProcess #5 ...
2024-07-15 11:46:51.431 | INFO     | src.data_manager.preprocess_tools:__6_convert_label_to_rate_info:47 - Start PreProcess #6 ...
2024-07-15 11:47:03.462 | INFO     | src.data_manager.preprocess_tools:__7_convert_distance_to_smile:49 - Start PreProcess #7 ...
2024-07-15 11:47:03.715 | INFO     | src.data_manager.preprocess_tools:__8_category_encoding:51 - Start PreProcess #8 ...

以上で準備完了。

スポンサーリンク

1.血統データの分析¶

読み込んだ血統データは5代血統まであり分析が大変なので、まずは簡単に1代血統を調べてみて、何が分かるか調べてみる

In [13]:
# よって、1代血統の情報だけに絞り込み
dfgen1 = dfblood[["horseId", "gen1", "gen1ID"]].drop_duplicates(subset=["horseId", "gen1ID"], ignore_index=True)
dfgen1["gen1"] = dfgen1["gen1"].str.split("\n", n=1, expand=True)[0]
dfgen1
Out[13]:
horseId gen1 gen1ID
0 1986102130 ジュニアス 000a0001af
1 1986102130 ナオユキ 1955102525
2 1987109113 Niniski 000a00199e
3 1987109113 Martinova 000a00ab32
4 1988105984 ギャロップダイナ 1980101941
232987 2021100142 Catch A Glimpse 000a0135d6
232988 2021107111 アメリカンペイトリオット 000a013bba
232989 2021107111 エイシンドナウ 2011105568
232990 2021105244 ブリックスアンドモルタル 000a014377
232991 2021105244 マンハッタンセレブ 2003102531

232992 rows × 3 columns

In [16]:
# 出走情報に1代血統の情報を追加する
# 1代血統には、母と父の情報が入っている。
# ちょっと見てみる
dfgen1
Out[16]:
horseId gen1 gen1ID
0 1986102130 ジュニアス 000a0001af
1 1986102130 ナオユキ 1955102525
2 1987109113 Niniski 000a00199e
3 1987109113 Martinova 000a00ab32
4 1988105984 ギャロップダイナ 1980101941
232987 2021100142 Catch A Glimpse 000a0135d6
232988 2021107111 アメリカンペイトリオット 000a013bba
232989 2021107111 エイシンドナウ 2011105568
232990 2021105244 ブリックスアンドモルタル 000a014377
232991 2021105244 マンハッタンセレブ 2003102531

232992 rows × 3 columns

一つのhorseIdに2つの親のhorseIdが紐づいている

In [19]:
# なので配列の奇数番目と偶数番目を参照できるやつを使って、
# 種牡馬の情報と繫殖牝馬の情報に分ける
stallion_dict = dfgen1.loc[dfgen1.index.tolist()[::2]].set_index("horseId").to_dict() 
# ↑これで種牡馬のみ取り出せる
# 同じ感じで繫殖牝馬も手に入れる
breed_dict = dfgen1.loc[dfgen1.index.tolist()[1::2]].set_index("horseId").to_dict()

種牡馬と繫殖牝馬の二つを出走情報へ追加する

In [21]:
df["stallionName"] = df["horseId"].map(stallion_dict["gen1"])
df["stallionId"] = df["horseId"].map(stallion_dict["gen1ID"])
df["breedName"] = df["horseId"].map(breed_dict["gen1"])
df["breedId"] = df["horseId"].map(breed_dict["gen1ID"])
df[["stallionId", "stallionName", "breedId", "breedName"]].tail(20)
Out[21]:
stallionId stallionName breedId breedName
1126053 000a0113a1 ディスクリートキャット 2007101796 メイショウコブシ
1126054 2004103328 スクリーンヒーロー 000a010ac0 パーソナルレジェンド
1126055 2001100650 メイショウボーラー 1997105297 グリーンオリーヴ
1126056 2001103460 キングカメハメハ 2008101424 クイーンオリーブ
1126057 2008103244 リアルインパクト 2012102312 ブリーズヴェール
1126058 2012104511 ドゥラメンテ 000a013eb4 カレドニアレディ
1126059 2013100612 ファインニードル 2008101286 エーシンパナギア
1126060 000a013bba アメリカンペイトリオット 2011100540 ハッシュ
1126061 2001190004 バゴ 2013106419 ウートゥルメール
1126062 000a013bba アメリカンペイトリオット 2015101588 ヴェスティージ
1126063 2003110212 キンシャサノキセキ 000a0114af サイレントセンティネル
1126064 2001103114 ダイワメジャー 2009106653 コスモルーシー
1126065 2007102923 ヴィクトワールピサ 1998103160 ダンシングブルーム
1126066 1994109686 タイキシャトル 2006104237 カリオンレディ
1126067 2010105827 キズナ 2005102351 ビーチアイドル
1126068 000a012056 Siyouni 000a01460b オーティニャック
1126069 2010105827 キズナ 2010103683 イニシャルダブル
1126070 2008103552 ロードカナロア 2001102686 ニシノビギン
1126071 2011104063 サトノアラジン 2012100606 ハギノナトゥーラ
1126072 000a0113a1 ディスクリートキャット 2010100683 デイドリーマー
スポンサーリンク

2.種牡馬の調査¶

父親の産駒の出走数の分布を確認してみる

In [23]:
dfstallion_cnt = df.groupby(["stallionId", "stallionName"])["horseId"].count().sort_values()
dfstallion_cnt
Out[23]:
stallionId  stallionName  
000a01d476  Smooth Daddy          1
1996106813  イシノナイト                1
000a0114fc  Loup Solitaire        1
000a00218c  Personal Flag         1
000a0021b9  Dare and Go           1
                              ...  
2001103038  ハーツクライ            16364
1998110135  クロフネ              17070
000a00033a  サンデーサイレンス         17716
2001103460  キングカメハメハ          20773
2002100816  ディープインパクト         21570
Name: horseId, Length: 2104, dtype: int64
In [24]:
# ディープインパクトやキングカメハメハが大量にいるから、偏りが激しそう
dfstallion_cnt.describe()
Out[24]:
count     2104.000000
mean       535.205798
std       1763.336065
min          1.000000
25%         10.000000
50%         42.000000
75%        207.500000
max      21570.000000
Name: horseId, dtype: float64

1頭の種牡馬の産駒たちの合計出走回数の平均が500回強であるにも関わらず、
全体の分布の中央値は42回しかない
さらに言えば、75%分位つまり4分の3の種牡馬の産駒は200回程度までしか走っていない。
恐ろしく偏りがすさまじい

あくまでこれは出走回数の話なので、産駒の数で見てみる

In [31]:
dfgen1.loc[dfgen1.index.tolist()[::2]].groupby(["gen1ID", "gen1"])["horseId"].count().sort_values()
Out[31]:
gen1ID      gen1      
000a012900  Bayern           1
000a002031  Mukaddamah       1
000a002034  Turgeon          1
000a01ade3  Assessor         1
000a01adf0  Cyborg           1
                          ... 
1993109188  ダンスインザダーク     1421
1992109618  フジキセキ         1426
1998110135  クロフネ          1507
2001103460  キングカメハメハ      1612
2002100816  ディープインパクト     1614
Name: horseId, Length: 2149, dtype: int64

やっぱり当然ながら偏りが激しい

In [32]:
# 分布も確認
dfgen1.loc[dfgen1.index.tolist()[::2]].groupby(["gen1ID", "gen1"])["horseId"].count().describe()
Out[32]:
count    2149.000000
mean       54.209400
std       160.699399
min         1.000000
25%         1.000000
50%         5.000000
75%        24.000000
max      1614.000000
Name: horseId, dtype: float64

出走回数と大差ない結果
やはり種牡馬は偏りが激しく、特定の種牡馬に産駒が集中する

他にも調べてみたが、繫殖牝馬はあまり偏りは大きくない(とは言っても少し偏りはある)
とはいえ、やはり調べると母より母父の方が大事だと分かった。
つまり、父と母父、この二つで血統の偏りが見られることから、
父系の血統を見るのが重要なのではないかと容易に想像できる。

スポンサーリンク

3.父と母父に絞って様子を見る¶

まずは母父の情報を追加しないといけない
ので、以下の関数を作ります。

In [35]:
from typing import Literal
def blood_analyze(mode: Literal["s", "b", "sb", "bs", "ss", "bb"]):
    index_map = {
        "s": (0, "stallion", "gen1"), "ss": (0, "sStallion", "gen2"), "sb": (8, "sBreed", "gen2"),
        "b": (16, "breed", "gen1"), "bs": (16, "bStallion", "gen2"), "bb": (24, "bBreed", "gen2")
    }
    idx, prefix, genCol = index_map[mode]
    idf = dfblood.iloc[idx::32].reset_index(drop=True)
    idf[genCol] = idf[genCol].str.split("\n", expand=True, n=1)[0]
    horseId = "horseId"
    df[f"{prefix}Id"] = df[horseId].map(idf.set_index(horseId)[f"{genCol}ID"])
    df[f"{prefix}Name"] = df[horseId].map(idf.set_index(horseId)[f"{genCol}"])
    return df
    
    

以下のように使う。簡単に親たちの情報を出走情報についかできる

In [36]:
df = blood_analyze("bs")
df[["horseId", "stallionId", "stallionName", "bStallionId", "bStallionName"]]
Out[36]:
horseId stallionId stallionName bStallionId bStallionName
0 1997100761 000a000d4b エブロス 000a000081 ブレイヴェストローマン
1 1997100656 000a000013 アフリート 000a000d2e ストームオンザルース
2 1997100203 1982101222 サクラユタカオー 000a000258 ノーザンテースト
3 1997104609 000a000d87 ロイヤルアカデミーII 000a0001ff マナード
4 1997106623 1988106402 カリスタグローリ 000a00010d エンペリー
1126068 2019103898 000a012056 Siyouni 000a014559 Solon
1126069 2019106102 2010105827 キズナ 000a00fa35 ウォーエンブレム
1126070 2017102603 2008103552 ロードカナロア 1989109110 パラダイスクリーク
1126071 2019100653 2011104063 サトノアラジン 2001103114 ダイワメジャー
1126072 2018103205 000a0113a1 ディスクリートキャット 2000101426 ネオユニヴァース

1126073 rows × 5 columns

レース条件ごとに産駒の分布に違いがあるのか確かめる

In [37]:
# とりあえずレース条件の種類を確認したい
df["raceDetail"].unique()
Out[37]:
array(['4歳未勝利', '4歳新馬', '4歳以上500万下', '4歳500万下', '4歳以上900万下', '4歳以上オープン',
       '4歳以上1600万下', '4歳オープン', '4歳未出走', '5歳以上オープン', '4歳900万下', '3歳新馬',
       '3歳未勝利', '3歳オープン', '3歳500万下', '3歳未出走', '3歳以上オープン', '3歳900万下',
       '2歳新馬', '3歳以上500万下', '3歳以上1000万下', '2歳未勝利', '2歳オープン', '3歳以上1600万下',
       '2歳500万下', '4歳以上1000万下', '3歳1000万下', '3歳以上1勝クラス', '3歳以上2勝クラス',
       '3歳以上3勝クラス', '2歳1勝クラス', '3歳1勝クラス', '4歳以上1勝クラス', '4歳以上2勝クラス',
       '4歳以上3勝クラス'], dtype=object)

レースのクラス分けは、昔は獲得賞金で決まっていたそうだが、最近だと勝利回数でクラスが分けられる
詳しい内容は調べると早い

なので、以下の表のようにグレードを用意して対応付けを分かりやすくする

獲得賞金 クラス グレード
0 新馬, 未勝利 0
500万下 1勝クラス 1
1000万下, 900万下 2勝クラス 2
1600万下 3勝クラス 3
それ以上 オープン 4
G3 5
G2 6
G1 7

グレード分けする関数を作る

In [38]:
def map_race_grade(data: str):
    if re.search(r"\(G1\)", data) or re.search(r"\(GI\)", data):
        return 7
    if re.search(r"\(G2\)", data) or re.search(r"\(GII\)", data):
        return 6
    if re.search(r"\(G3\)", data) or re.search(r"\(GIII\)", data):
        return 5
    return None

grade_mapping_dict = {
    '4歳未勝利':0, '4歳新馬':0, '4歳以上500万下':1, '4歳500万下':1, '4歳以上900万下':2, '4歳以上オープン':4,
       '4歳以上1600万下':3, '4歳オープン':4, '4歳未出走':0, '5歳以上オープン':4, '4歳900万下':2, '3歳新馬':0,
       '3歳未勝利':0, '3歳オープン':4, '3歳500万下':1, '3歳未出走':0, '3歳以上オープン':4, '3歳900万下':2,
       '2歳新馬':0, '3歳以上500万下':1, '3歳以上1000万下':2, '2歳未勝利':0, '2歳オープン':4, '3歳以上1600万下':3,
       '2歳500万下':1, '4歳以上1000万下':2, '3歳1000万下':2, '3歳以上1勝クラス':1, '3歳以上2勝クラス':2,
       '3歳以上3勝クラス':3, '2歳1勝クラス':1, '3歳1勝クラス':1, '4歳以上1勝クラス':1, '4歳以上2勝クラス':2,
       '4歳以上3勝クラス':3
}
In [39]:
# 以下のようにしてraceGradeカラムを追加する
idf = df["raceName"].map(map_race_grade)
idf = idf[idf.notna()]
df["raceGrade"] = pd.concat([idf, df[~df.index.isin(idf.index)]["raceDetail"].map(grade_mapping_dict)])
# G1のレースに絞ってみて、ちゃんとグレード分けできたか確認
df[df["raceGrade"].isin([7])]["raceName"].unique()
Out[39]:
array(['第17回フェブラリーS(GI)', '第30回高松宮記念(GI)', '第60回桜花賞(GI)', '第60回皐月賞(GI)',
       '第121回天皇賞(春)(GI)', '第5回NHKマイルカップ(GI)', '第61回優駿牝馬(GI)',
       '第67回東京優駿(GI)', '第50回安田記念(GI)', '第41回宝塚記念(GI)', '第34回スプリンターズS(GI)',
       '第5回秋華賞(GI)', '第61回菊花賞(GI)', '第122回天皇賞(秋)(GI)', '第25回エリザベス女王杯(GI)',
       '第17回マイルチャンピオンS(GI)', '第1回ジャパンカップダート(GI)', '第20回ジャパンカップ(GI)',
       '第52回阪神3歳牝馬S(GI)', '第52回朝日杯3歳ステークス(GI)', '第45回有馬記念(GI)',
       '第18回フェブラリーS(GI)', '第31回高松宮記念(GI)', '第61回桜花賞(GI)', '第61回皐月賞(GI)',
       '第123回天皇賞(春)(GI)', '第6回NHKマイルカップ(GI)', '第62回優駿牝馬(GI)',
       '第68回東京優駿(GI)', '第51回安田記念(GI)', '第42回宝塚記念(GI)', '第35回スプリンターズS(GI)',
       '第6回秋華賞(GI)', '第62回菊花賞(GI)', '第124回天皇賞(秋)(GI)', '第26回エリザベス女王杯(GI)',
       '第18回マイルチャンピオンS(GI)', '第2回ジャパンカップダート(GI)', '第21回ジャパンカップ(GI)',
       '第53回阪神ジュベナイルF(GI)', '第53回朝日杯FS(GI)', '第46回有馬記念(GI)',
       '第19回フェブラリーS(GI)', '第32回高松宮記念(GI)', '第62回桜花賞(GI)', '第62回皐月賞(GI)',
       '第125回天皇賞(春)(GI)', '第7回NHKマイルカップ(GI)', '第63回優駿牝馬(GI)',
       '第69回東京優駿(GI)', '第52回安田記念(GI)', '第43回宝塚記念(GI)', '第36回スプリンターズS(GI)',
       '第7回秋華賞(GI)', '第63回菊花賞(GI)', '第126回天皇賞(秋)(GI)', '第27回エリザベス女王杯(GI)',
       '第19回マイルチャンピオンS(GI)', '第3回ジャパンカップダート(GI)', '第22回ジャパンカップ(GI)',
       '第54回阪神ジュベナイルF(GI)', '第54回朝日杯FS(GI)', '第47回有馬記念(GI)',
       '第20回フェブラリーS(GI)', '第33回高松宮記念(GI)', '第63回桜花賞(GI)', '第63回皐月賞(GI)',
       '第127回天皇賞(春)(GI)', '第8回NHKマイルカップ(GI)', '第64回優駿牝馬(GI)',
       '第70回東京優駿(GI)', '第53回安田記念(GI)', '第44回宝塚記念(GI)', '第37回スプリンターズS(GI)',
       '第8回秋華賞(GI)', '第64回菊花賞(GI)', '第128回天皇賞(秋)(GI)', '第28回エリザベス女王杯(GI)',
       '第20回マイルチャンピオンS(GI)', '第4回ジャパンカップダート(GI)', '第23回ジャパンカップ(GI)',
       '第55回阪神ジュベナイルF(GI)', '第55回朝日杯FS(GI)', '第48回有馬記念(GI)',
       '第21回フェブラリーS(GI)', '第34回高松宮記念(GI)', '第64回桜花賞(GI)', '第64回皐月賞(GI)',
       '第129回天皇賞(春)(GI)', '第9回NHKマイルカップ(GI)', '第65回優駿牝馬(GI)',
       '第71回東京優駿(GI)', '第54回安田記念(GI)', '第45回宝塚記念(GI)', '第38回スプリンターズS(GI)',
       '第9回秋華賞(GI)', '第65回菊花賞(GI)', '第130回天皇賞(秋)(GI)', '第29回エリザベス女王杯(GI)',
       '第21回マイルチャンピオンS(GI)', '第5回ジャパンカップダート(GI)', '第24回ジャパンカップ(GI)',
       '第56回阪神ジュベナイルF(GI)', '第56回朝日杯FS(GI)', '第49回有馬記念(GI)',
       '第22回フェブラリーS(GI)', '第35回高松宮記念(GI)', '第65回桜花賞(GI)', '第65回皐月賞(GI)',
       '第131回天皇賞(春)(GI)', '第10回NHKマイルカップ(GI)', '第66回優駿牝馬(GI)',
       '第72回東京優駿(GI)', '第55回安田記念(GI)', '第46回宝塚記念(GI)', '第39回スプリンターズS(GI)',
       '第10回秋華賞(GI)', '第66回菊花賞(GI)', '第132回天皇賞(秋)(GI)',
       '第30回エリザベス女王杯(GI)', '第22回マイルチャンピオンS(GI)', '第6回ジャパンカップダート(GI)',
       '第25回ジャパンカップ(GI)', '第57回阪神ジュベナイルF(GI)', '第57回朝日フューチュリティ(GI)',
       '第50回有馬記念(GI)', '第23回フェブラリーS(GI)', '第36回高松宮記念(GI)', '第66回桜花賞(GI)',
       '第66回皐月賞(GI)', '第133回天皇賞(春)(GI)', '第11回NHKマイルカップ(GI)',
       '第1回ヴィクトリアマイル(GI)', '第67回優駿牝馬(GI)', '第73回東京優駿(GI)', '第56回安田記念(GI)',
       '第47回宝塚記念(GI)', '第40回スプリンターズS(GI)', '第11回秋華賞(GI)', '第67回菊花賞(GI)',
       '第134回天皇賞(秋)(GI)', '第31回エリザベス女王杯(GI)', '第23回マイルチャンピオンS(GI)',
       '第7回ジャパンカップダート(GI)', '第26回ジャパンカップ(GI)', '第58回阪神ジュベナイルF(GI)',
       '第58回朝日フューチュリティ(GI)', '第51回有馬記念(GI)', '第24回フェブラリーS(GI)',
       '第37回高松宮記念(GI)', '第67回桜花賞(GI)', '第67回皐月賞(GI)', '第135回天皇賞(春)(GI)',
       '第12回NHKマイルカップ(GI)', '第2回ヴィクトリアマイル(GI)', '第68回優駿牝馬(GI)',
       '第74回東京優駿(GI)', '第57回安田記念(GI)', '第48回宝塚記念(GI)', '第41回スプリンターズS(GI)',
       '第12回秋華賞(GI)', '第68回菊花賞(GI)', '第136回天皇賞(秋)(GI)',
       '第32回エリザベス女王杯(GI)', '第24回マイルチャンピオンS(GI)', '第8回ジャパンカップダート(GI)',
       '第27回ジャパンカップ(GI)', '第59回阪神ジュベナイルF(GI)', '第59回朝日フューチュリティ(GI)',
       '第52回有馬記念(GI)', '第25回フェブラリーS(GI)', '第38回高松宮記念(GI)', '第68回桜花賞(GI)',
       '第68回皐月賞(GI)', '第137回天皇賞(春)(GI)', '第13回NHKマイルカップ(GI)',
       '第3回ヴィクトリアマイル(GI)', '第69回優駿牝馬(GI)', '第75回東京優駿(GI)', '第58回安田記念(GI)',
       '第49回宝塚記念(GI)', '第42回スプリンターズS(GI)', '第13回秋華賞(GI)', '第69回菊花賞(GI)',
       '第138回天皇賞(秋)(GI)', '第33回エリザベス女王杯(GI)', '第25回マイルチャンピオンS(GI)',
       '第28回ジャパンカップ(GI)', '第9回ジャパンカップダート(GI)', '第60回阪神ジュベナイルF(GI)',
       '第60回朝日フューチュリティ(GI)', '第53回有馬記念(GI)', '第26回フェブラリーS(GI)',
       '第39回高松宮記念(GI)', '第69回桜花賞(GI)', '第69回皐月賞(GI)', '第139回天皇賞(春)(GI)',
       '第14回NHKマイルカップ(GI)', '第4回ヴィクトリアマイル(GI)', '第70回優駿牝馬(GI)',
       '第76回東京優駿(GI)', '第59回安田記念(GI)', '第50回宝塚記念(GI)', '第43回スプリンターズS(GI)',
       '第14回秋華賞(GI)', '第70回菊花賞(GI)', '第140回天皇賞(秋)(GI)',
       '第34回エリザベス女王杯(GI)', '第26回マイルチャンピオンS(GI)', '第29回ジャパンカップ(GI)',
       '第10回ジャパンカップダート(GI)', '第61回阪神ジュベナイルF(GI)', '第61回朝日フューチュリティ(GI)',
       '第54回有馬記念(GI)', '第27回フェブラリーS(G1)', '第40回高松宮記念(G1)', '第70回桜花賞(G1)',
       '第70回皐月賞(G1)', '第141回天皇賞(春)(G1)', '第15回NHKマイルカップ(G1)',
       '第5回ヴィクトリアマイル(G1)', '第71回優駿牝馬(G1)', '第77回東京優駿(G1)', '第60回安田記念(G1)',
       '第51回宝塚記念(G1)', '第44回スプリンターズS(G1)', '第15回秋華賞(G1)', '第71回菊花賞(G1)',
       '第142回天皇賞(秋)(G1)', '第35回エリザベス女王杯(G1)', '第27回マイルチャンピオンS(G1)',
       '第30回ジャパンカップ(G1)', '第11回ジャパンカップダート(G1)', '第62回阪神ジュベナイルF(G1)',
       '第62回朝日フューチュリティ(G1)', '第55回有馬記念(G1)', '第28回フェブラリーS(G1)',
       '第41回高松宮記念(G1)', '第71回桜花賞(G1)', '第71回皐月賞(G1)', '第143回天皇賞(春)(G1)',
       '第16回NHKマイルカップ(G1)', '第6回ヴィクトリアマイル(G1)', '第72回優駿牝馬(G1)',
       '第78回東京優駿(G1)', '第61回安田記念(G1)', '第52回宝塚記念(G1)', '第45回スプリンターズS(G1)',
       '第24回マイルCS南部杯(G1)', '第16回秋華賞(G1)', '第72回菊花賞(G1)',
       '第144回天皇賞(秋)(G1)', '第36回エリザベス女王杯(G1)', '第28回マイルチャンピオンS(G1)',
       '第31回ジャパンカップ(G1)', '第12回ジャパンカップダート(G1)', '第63回阪神ジュベナイルF(G1)',
       '第63回朝日フューチュリティ(G1)', '第56回有馬記念(G1)', '第29回フェブラリーS(G1)',
       '第42回高松宮記念(G1)', '第72回桜花賞(G1)', '第72回皐月賞(G1)', '第145回天皇賞(春)(G1)',
       '第17回NHKマイルカップ(G1)', '第7回ヴィクトリアマイル(G1)', '第73回優駿牝馬(G1)',
       '第79回東京優駿(G1)', '第62回安田記念(G1)', '第53回宝塚記念(G1)', '第46回スプリンターズS(G1)',
       '第17回秋華賞(G1)', '第73回菊花賞(G1)', '第146回天皇賞(秋)(G1)',
       '第37回エリザベス女王杯(G1)', '第29回マイルチャンピオンS(G1)', '第32回ジャパンカップ(G1)',
       '第13回ジャパンカップダート(G1)', '第64回阪神ジュベナイルF(G1)', '第64回朝日フューチュリティ(G1)',
       '第57回有馬記念(G1)', '第30回フェブラリーS(G1)', '第43回高松宮記念(G1)', '第73回桜花賞(G1)',
       '第73回皐月賞(G1)', '第147回天皇賞(春)(G1)', '第18回NHKマイルカップ(G1)',
       '第8回ヴィクトリアマイル(G1)', '第74回優駿牝馬(G1)', '第80回東京優駿(G1)', '第63回安田記念(G1)',
       '第54回宝塚記念(G1)', '第47回スプリンターズS(G1)', '第18回秋華賞(G1)', '第74回菊花賞(G1)',
       '第148回天皇賞(秋)(G1)', '第38回エリザベス女王杯(G1)', '第30回マイルチャンピオンS(G1)',
       '第33回ジャパンカップ(G1)', '第14回ジャパンカップダート(G1)', '第65回阪神ジュベナイルF(G1)',
       '第65回朝日フューチュリティ(G1)', '第58回有馬記念(G1)', '第31回フェブラリーS(G1)',
       '第44回高松宮記念(G1)', '第74回桜花賞(G1)', '第74回皐月賞(G1)', '第149回天皇賞(春)(G1)',
       '第19回NHKマイルカップ(G1)', '第9回ヴィクトリアマイル(G1)', '第75回優駿牝馬(G1)',
       '第81回東京優駿(G1)', '第64回安田記念(G1)', '第55回宝塚記念(G1)', '第48回スプリンターズS(G1)',
       '第19回秋華賞(G1)', '第75回菊花賞(G1)', '第150回天皇賞(秋)(G1)',
       '第39回エリザベス女王杯(G1)', '第31回マイルチャンピオンS(G1)', '第34回ジャパンカップ(G1)',
       '第15回チャンピオンズカップ(G1)', '第66回阪神ジュベナイルF(G1)', '第66回朝日フューチュリティ(G1)',
       '第59回有馬記念(G1)', '第32回フェブラリーS(G1)', '第45回高松宮記念(G1)', '第75回桜花賞(G1)',
       '第75回皐月賞(G1)', '第151回天皇賞(春)(G1)', '第20回NHKマイルカップ(G1)',
       '第10回ヴィクトリアマイル(G1)', '第76回優駿牝馬(G1)', '第82回東京優駿(G1)',
       '第65回安田記念(G1)', '第56回宝塚記念(G1)', '第49回スプリンターズS(G1)', '第20回秋華賞(G1)',
       '第76回菊花賞(G1)', '第152回天皇賞(秋)(G1)', '第40回エリザベス女王杯(G1)',
       '第32回マイルチャンピオンS(G1)', '第35回ジャパンカップ(G1)', '第16回チャンピオンズカップ(G1)',
       '第67回阪神ジュベナイルF(G1)', '第67回朝日フューチュリティ(G1)', '第60回有馬記念(G1)',
       '第33回フェブラリーS(G1)', '第46回高松宮記念(G1)', '第76回桜花賞(G1)', '第76回皐月賞(G1)',
       '第153回天皇賞(春)(G1)', '第21回NHKマイルカップ(G1)', '第11回ヴィクトリアマイル(G1)',
       '第77回優駿牝馬(G1)', '第83回東京優駿(G1)', '第66回安田記念(G1)', '第57回宝塚記念(G1)',
       '第50回スプリンターズS(G1)', '第21回秋華賞(G1)', '第77回菊花賞(G1)',
       '第154回天皇賞(秋)(G1)', '第41回エリザベス女王杯(G1)', '第33回マイルチャンピオンS(G1)',
       '第36回ジャパンカップ(G1)', '第17回チャンピオンズカップ(G1)', '第68回阪神ジュベナイルF(G1)',
       '第68回朝日フューチュリティ(G1)', '第61回有馬記念(G1)', '第34回フェブラリーS(G1)',
       '第47回高松宮記念(G1)', '第61回大阪杯(G1)', '第77回桜花賞(G1)', '第77回皐月賞(G1)',
       '第155回天皇賞(春)(G1)', '第22回NHKマイルカップ(G1)', '第12回ヴィクトリアマイル(G1)',
       '第78回優駿牝馬(G1)', '第84回東京優駿(G1)', '第67回安田記念(G1)', '第58回宝塚記念(G1)',
       '第51回スプリンターズS(G1)', '第22回秋華賞(G1)', '第78回菊花賞(G1)',
       '第156回天皇賞(秋)(G1)', '第42回エリザベス女王杯(G1)', '第34回マイルチャンピオンS(G1)',
       '第37回ジャパンカップ(G1)', '第18回チャンピオンズカップ(G1)', '第69回阪神ジュベナイルF(G1)',
       '第69回朝日フューチュリティ(G1)', '第62回有馬記念(G1)', '第34回ホープフルステークス(G1)',
       '第35回フェブラリーS(G1)', '第48回高松宮記念(G1)', '第62回大阪杯(G1)', '第78回桜花賞(G1)',
       '第78回皐月賞(G1)', '第157回天皇賞(春)(G1)', '第23回NHKマイルカップ(G1)',
       '第13回ヴィクトリアマイル(G1)', '第79回優駿牝馬(G1)', '第85回東京優駿(G1)',
       '第68回安田記念(G1)', '第59回宝塚記念(G1)', '第52回スプリンターズS(G1)', '第23回秋華賞(G1)',
       '第79回菊花賞(G1)', '第158回天皇賞(秋)(G1)', '第18回JBCスプリント(G1)',
       '第18回JBCクラシック(G1)', '第8回JBCレディスクラシ(G1)', '第43回エリザベス女王杯(G1)',
       '第35回マイルチャンピオンS(G1)', '第38回ジャパンカップ(G1)', '第19回チャンピオンズカップ(G1)',
       '第70回阪神ジュベナイルF(G1)', '第70回朝日フューチュリティ(G1)', '第63回有馬記念(G1)',
       '第35回ホープフルステークス(G1)', '第36回フェブラリーS(G1)', '第49回高松宮記念(G1)',
       '第63回大阪杯(G1)', '第79回桜花賞(G1)', '第79回皐月賞(G1)', '第159回天皇賞(春)(G1)',
       '第24回NHKマイルカップ(G1)', '第14回ヴィクトリアマイル(G1)', '第80回優駿牝馬(G1)',
       '第86回東京優駿(G1)', '第69回安田記念(G1)', '第60回宝塚記念(G1)', '第53回スプリンターズS(G1)',
       '第24回秋華賞(G1)', '第80回菊花賞(G1)', '第160回天皇賞(秋)(G1)',
       '第44回エリザベス女王杯(G1)', '第36回マイルチャンピオンS(G1)', '第39回ジャパンカップ(G1)',
       '第20回チャンピオンズカップ(G1)', '第71回阪神ジュベナイルF(G1)', '第71回朝日フューチュリティ(G1)',
       '第64回有馬記念(G1)', '第36回ホープフルステークス(G1)', '第37回フェブラリーS(G1)',
       '第50回高松宮記念(G1)', '第64回大阪杯(G1)', '第80回桜花賞(G1)', '第80回皐月賞(G1)',
       '第161回天皇賞(春)(G1)', '第25回NHKマイルカップ(G1)', '第15回ヴィクトリアマイル(G1)',
       '第81回優駿牝馬(G1)', '第87回東京優駿(G1)', '第70回安田記念(G1)', '第61回宝塚記念(G1)',
       '第54回スプリンターズS(G1)', '第25回秋華賞(G1)', '第81回菊花賞(G1)',
       '第162回天皇賞(秋)(G1)', '第45回エリザベス女王杯(G1)', '第37回マイルチャンピオンS(G1)',
       '第40回ジャパンカップ(G1)', '第21回チャンピオンズカップ(G1)', '第72回阪神ジュベナイルF(G1)',
       '第72回朝日フューチュリティ(G1)', '第37回ホープフルステークス(G1)', '第65回有馬記念(G1)',
       '第38回フェブラリーS(G1)', '第51回高松宮記念(G1)', '第65回大阪杯(G1)', '第81回桜花賞(G1)',
       '第81回皐月賞(G1)', '第163回天皇賞(春)(G1)', '第26回NHKマイルカップ(G1)',
       '第16回ヴィクトリアマイル(G1)', '第82回優駿牝馬(G1)', '第88回東京優駿(G1)',
       '第71回安田記念(G1)', '第62回宝塚記念(G1)', '第55回スプリンターズS(G1)', '第26回秋華賞(G1)',
       '第82回菊花賞(G1)', '第164回天皇賞(秋)(G1)', '第46回エリザベス女王杯(G1)',
       '第38回マイルチャンピオンS(G1)', '第41回ジャパンカップ(G1)', '第22回チャンピオンズカップ(G1)',
       '第73回阪神ジュベナイルF(G1)', '第73回朝日フューチュリティ(G1)', '第66回有馬記念(G1)',
       '第38回ホープフルステークス(G1)', '第39回フェブラリーS(G1)', '第52回高松宮記念(G1)',
       '第66回大阪杯(G1)', '第82回桜花賞(G1)', '第82回皐月賞(G1)', '第165回天皇賞(春)(G1)',
       '第27回NHKマイルカップ(G1)', '第17回ヴィクトリアマイル(G1)', '第83回優駿牝馬(G1)',
       '第89回東京優駿(G1)', '第72回安田記念(G1)', '第63回宝塚記念(G1)', '第56回スプリンターズS(G1)',
       '第27回秋華賞(G1)', '第83回菊花賞(G1)', '第166回天皇賞(秋)(G1)',
       '第47回エリザベス女王杯(G1)', '第39回マイルチャンピオンS(G1)', '第42回ジャパンカップ(G1)',
       '第23回チャンピオンズカップ(G1)', '第74回阪神ジュベナイルF(G1)', '第74回朝日フューチュリティ(G1)',
       '第67回有馬記念(G1)', '第39回ホープフルステークス(G1)', '第40回フェブラリーS(G1)',
       '第53回高松宮記念(G1)', '第67回大阪杯(G1)', '第83回桜花賞(G1)', '第83回皐月賞(G1)',
       '第167回天皇賞(春)(G1)', '第28回NHKマイルカップ(G1)', '第18回ヴィクトリアマイル(G1)',
       '第84回優駿牝馬(G1)', '第90回東京優駿(G1)', '第73回安田記念(G1)', '第64回宝塚記念(G1)',
       '第57回スプリンターズS(G1)', '第28回秋華賞(G1)', '第84回菊花賞(G1)',
       '第168回天皇賞(秋)(G1)', '第48回エリザベス女王杯(G1)', '第40回マイルチャンピオンS(G1)',
       '第43回ジャパンカップ(G1)', '第24回チャンピオンズカップ(G1)', '第75回阪神ジュベナイルF(G1)',
       '第75回朝日フューチュリティ(G1)', '第68回有馬記念(G1)', '第40回ホープフルステークス(G1)'],
      dtype=object)

多分イケて走

スポンサーリンク

4.重賞とレース条件に絞り込んで調査¶

ということでここから重賞クラスに絞って調べてみる

In [40]:
# 年度ごとに調べるようにする
df["year"] = df["raceDate"].dt.year

# レース条件ごとに調べる
field_dist = ["field", "dist_cat"]
dfg_fd = df[df["raceGrade"].isin([5,6,7])].groupby(field_dist)

レース条件ごとに年度別で重賞クラスに出走した競走馬の種牡馬と母父の分布を確認する
ワードクラウドを使って視覚的に確認する。
ワードクラウドは対象のテキストに含まれている単語の分布を文字の大きさから判断できるもの
文字が大きければ大きいほどたくさんその単語があることを意味する。

ワードクラウドを使うにはwordcloudというライブラリをインストールする必要がある。もうpoetry経由でインストール済

スポンサーリンク

5.WordCloudを使って種牡馬産駒の出走回数の可視化¶

In [41]:
colormap = "RdYlBu" # 見やすそうなカラーマップなら何でもいい
# 日本語フォントを使う
font_path = "C:/Windows/Fonts/meiryo.ttc"

# linuxの場合は以下にあるかも(Macも同じ?)
# font_path="/usr/share/fonts/truetype/fonts-japanese-gothic.ttf"
group_list = []
for group in [(f, d) for f in ["芝", "ダ"] for d in "SMILE" if f!="ダ" or d!="E"]:
    idf = dfg_fd.get_group(group)
    print(",".join(list(group)+["重賞クラス"]))
    plt.figure(figsize=(24,9))
    year_list = idf["year"].unique()
    nyear = idf["year"].nunique()
    rows = sum([True, nyear > 8, nyear > 16])
    cols = 8
    for idx, (year, idfy) in enumerate(idf.groupby("year"), start=1):
        group_list += [idfy[["year", "stallionName"] + ["field", "dist_cat"]].value_counts().sort_values().tail(1).reset_index()]
        idfyg = idfy[["year", "stallionId", "stallionName"]].value_counts().sort_values().reset_index()
        word_list = []
        for row in idfyg.to_dict(orient="records"):
            word_list += [row["stallionName"]]*row["count"]
        random.shuffle(word_list)
        plt.subplot(rows, cols, idx)
        wordcloud = WordCloud(
            background_color="white",
            width=800,
            height=800,
            font_path=font_path,
            colormap=colormap
        ).generate(" ".join(word_list))
        plt.imshow(wordcloud, interpolation="bilinear")
        plt.title(year)
        plt.axis("off")
    plt.show()
芝,S,重賞クラス
芝,M,重賞クラス
芝,I,重賞クラス
芝,L,重賞クラス
芝,E,重賞クラス
ダ,S,重賞クラス
ダ,M,重賞クラス
ダ,I,重賞クラス
ダ,L,重賞クラス

別で貯めこんでいた情報を以下で分析する。
各レース条件と年度に対して、もっとも産駒が出走した種牡馬を一覧で出してる

In [42]:
dfgp = pd.concat(group_list)
idfgp = dfgp.groupby(["field", "dist_cat"])

dflist = []
index_list = []
for field in ["芝", "ダ"]:
    dist_list = "SMILE" if field == "芝" else "SMIL"
    for dist in dist_list:
        idfg = idfgp.get_group((field, dist))
        dflist += idfg.set_index("year")[["stallionName"]].T.to_dict(orient="records")
        index_list += ["-".join([field, dist])]
display(pd.DataFrame(dflist, index=index_list).T)
芝-S 芝-M 芝-I 芝-L 芝-E ダ-S ダ-M ダ-I ダ-L
2000 サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス エブロス ジェイドロバリー コマンダーインチーフ レオダーバン
2001 サクラバクシンオー サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス ミホシンザン アフリート コマンダーインチーフ アサティス
2002 サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス エンドスウィープ アフリート NaN モガンボ
2003 サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス フォーティナイナー フォーティナイナー フレンチデピュティ アフリート
2004 サクラバクシンオー サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス フォーティナイナー フォーティナイナー フォーティナイナー ブライアンズタイム
2005 サクラバクシンオー サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サクラバクシンオー アフリート ワイルドラッシュ サンデーサイレンス
2006 サクラバクシンオー サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス シャンハイ ブライアンズタイム ヘネシー サンデーサイレンス
2007 サクラバクシンオー サンデーサイレンス サンデーサイレンス サンデーサイレンス ダンスインザダーク ボストンハーバー ブライアンズタイム ブライアンズタイム ブライアンズタイム
2008 フジキセキ ダンスインザダーク サンデーサイレンス サンデーサイレンス エルコンドルパサー アフリート ブライアンズタイム ブライアンズタイム ブライアンズタイム
2009 サクラバクシンオー ダンスインザダーク ステイゴールド マンハッタンカフェ ダンスインザダーク アフリート ブライアンズタイム ワイルドラッシュ ブライアンズタイム
2010 サクラバクシンオー キングカメハメハ マンハッタンカフェ マンハッタンカフェ マンハッタンカフェ フジキセキ ワイルドラッシュ Unbridled’s Song NaN
2011 サクラバクシンオー キングカメハメハ ステイゴールド キングカメハメハ マンハッタンカフェ ワイルドラッシュ シンボリクリスエス ウォーエンブレム NaN
2012 サクラバクシンオー ディープインパクト ディープインパクト ディープインパクト ジャングルポケット クロフネ キングカメハメハ キングカメハメハ NaN
2013 サクラバクシンオー ディープインパクト ディープインパクト ディープインパクト ディープインパクト ゴールドアリュール キングカメハメハ キングカメハメハ NaN
2014 サクラバクシンオー ディープインパクト ディープインパクト ディープインパクト ディープインパクト ボストンハーバー キングカメハメハ キングカメハメハ NaN
2015 サクラバクシンオー ディープインパクト ディープインパクト ディープインパクト ディープインパクト マンハッタンカフェ キングカメハメハ キングカメハメハ NaN
2016 サクラバクシンオー ディープインパクト ディープインパクト ディープインパクト ディープインパクト サクラバクシンオー キングカメハメハ ゴールドアリュール NaN
2017 アドマイヤムーン ディープインパクト ディープインパクト ディープインパクト ハーツクライ サウスヴィグラス ゴールドアリュール キングカメハメハ NaN
2018 アドマイヤムーン ディープインパクト ディープインパクト ディープインパクト ハーツクライ シニスターミニスター キングカメハメハ キングカメハメハ NaN
2019 ロードカナロア ディープインパクト ディープインパクト ディープインパクト ディープインパクト ベーカバド ゴールドアリュール キングカメハメハ NaN
2020 ロードカナロア ディープインパクト ディープインパクト ディープインパクト ディープインパクト ロードカナロア ゴールドアリュール キングカメハメハ NaN
2021 ロードカナロア ディープインパクト ディープインパクト ディープインパクト ディープインパクト ヘニーヒューズ ヘニーヒューズ ゴールドアリュール NaN
2022 ロードカナロア ディープインパクト ディープインパクト ディープインパクト オルフェーヴル サウスヴィグラス ヘニーヒューズ パイロ NaN
2023 ロードカナロア ロードカナロア ディープインパクト ディープインパクト ディープインパクト ロードカナロア ヘニーヒューズ キズナ NaN

ぱっと見で、芝はサンデーサイレンスとディープインパクトが目立ち、ダートはかろうじてキングカメハメハが目立つ結果になっている

こうしてみると、芝は血統がかなり偏っている中、ダートはこれといった特徴的な血統が見れない
よって、ダートで活躍できる強い血統はなかなか出てこないように感じる。

スポンサーリンク

6.WordCloudを使って母父の産駒の出走回数の可視化¶

同じように母父でも見てみる

In [43]:
roup_list = []
for group in [(f, d) for f in ["芝", "ダ"] for d in "SMILE" if f!="ダ" or d!="E"]:
    idf = dfg_fd.get_group(group)
    print(", ".join(list(group)+["重賞クラス"]))
    # idf = idf[idf["label"].isin([1,])]
    plt.figure(figsize=(24, 9))
    year_list = idf["year"].unique()
    nyear = idf["year"].nunique()
    rows = sum([True, nyear>=9, nyear>=17])
    cols = 8
    for idx, (year, idfy) in enumerate(idf.groupby("year"), start=1):
        group_list += [idfy[["year", "bStallionName"]+["field", "dist_cat"]].value_counts().sort_values().tail(1).reset_index()]
        idfyg = idfy[["year", "bStallionId", "bStallionName"]].value_counts().sort_values().reset_index()
        word_list = []
        for row in idfyg.to_dict(orient="records"):
            word_list += [row["bStallionName"]]*row["count"]
        random.shuffle(word_list)

        plt.subplot(rows, cols, idx)
        wordcloud = WordCloud(
            background_color="white",
            width=800,
            height=800,
            font_path=font_path,
            colormap = colormap,
            ).generate(" ".join(word_list))

        plt.imshow(wordcloud, interpolation="bilinear")
        plt.title(year)
        plt.axis("off")
    plt.show()
芝, S, 重賞クラス
芝, M, 重賞クラス
芝, I, 重賞クラス
芝, L, 重賞クラス
芝, E, 重賞クラス
ダ, S, 重賞クラス
ダ, M, 重賞クラス
ダ, I, 重賞クラス
ダ, L, 重賞クラス
In [44]:
dfgp = pd.concat(group_list)
idfgp = dfgp.groupby(["field", "dist_cat"])

dflist = []
index_list = []
for field in ["芝", "ダ"]:
    dist_list = "SMILE" if field == "芝" else "SMIL"
    for dist in dist_list:
        idfg = idfgp.get_group((field, dist))
        dflist += idfg.set_index("year")[["bStallionName"]].T.to_dict(orient="records")
        index_list += ["-".join([field, dist])]
display(pd.DataFrame(dflist, index=index_list).T)
芝-S 芝-M 芝-I 芝-L 芝-E ダ-S ダ-M ダ-I ダ-L
2000 ノーザンテースト トウショウボーイ ノーザンテースト ディクタス Assert Be My Guest マルゼンスキー ノーザンテースト ノーザンテースト
2001 ノーザンテースト ノーザンテースト ノーザンテースト Nureyev Affirmed ハンターコム Danzig ラシアンルーブル ノーザンテースト
2002 ノーザンテースト ノーザンテースト ノーザンテースト ノーザンテースト ノーザンテースト ラッキーソブリン Danzig NaN ミルジョージ
2003 ノーザンテースト ノーザンテースト ノーザンテースト Caerleon Caerleon Slew o’ Gold ノーザンテースト トニービン ラッキーソブリン
2004 ノーザンテースト ノーザンテースト ノーザンテースト Caerleon マルゼンスキー ラッキーソブリン ノーザンテースト トニービン ラッキーソブリン
2005 ノーザンテースト ノーザンテースト ノーザンテースト ノーザンテースト サンデーサイレンス Green Forest ノーザンテースト Alydar サンデーサイレンス
2006 ノーザンテースト サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス ロングリート サンデーサイレンス サンデーサイレンス Alydar
2007 ノーザンテースト サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス アフリート サンデーサイレンス サンデーサイレンス ブレイヴェストローマン
2008 ノーザンテースト サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス リアルシャダイ
2009 サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス メジロライアン サンデーサイレンス サンデーサイレンス サンデーサイレンス
2010 サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス トニービン Nureyev サンデーサイレンス サンデーサイレンス NaN
2011 サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス メジロマックイーン サンデーサイレンス サンデーサイレンス NaN
2012 サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス Sadler’s Wells NaN
2013 サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス トニービン フォーティナイナー サンデーサイレンス トニービン NaN
2014 ブライアンズタイム サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス ブライアンズタイム NaN
2015 サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス タヤスツヨシ サンデーサイレンス サンデーサイレンス NaN
2016 サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス ノーザンテースト Storm Cat サンデーサイレンス サンデーサイレンス NaN
2017 サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス ワイルドラッシュ サンデーサイレンス ブライアンズタイム NaN
2018 サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス サンデーサイレンス スペシャルウィーク NaN
2019 マイネルラヴ サンデーサイレンス サンデーサイレンス サンデーサイレンス アグネスタキオン ブラックタキシード フレンチデピュティ サンデーサイレンス NaN
2020 マイネルラヴ キングカメハメハ サンデーサイレンス キングカメハメハ サンデーサイレンス ブラックタキシード ブライアンズタイム コマンダーインチーフ NaN
2021 ブライアンズタイム ディープインパクト ディープインパクト ディープインパクト サンデーサイレンス ファルブラヴ スペシャルウィーク サクラバクシンオー NaN
2022 サクラバクシンオー ディープインパクト ディープインパクト ディープインパクト サンデーサイレンス ロックオブジブラルタル キングカメハメハ スペシャルウィーク NaN
2023 ディープインパクト ディープインパクト ディープインパクト ディープインパクト Royal Anthem サウスヴィグラス スペシャルウィーク クロフネ NaN

芝で見るとサンデーサイレンスがほぼ一強、しかし直近だとディープインパクトが台頭してきている。
ディープインパクトは2019年没であるため、2020年以降からは2世とした産駒が多く出てくる可能性があり、母父にはディープインパクトといった流れが今後出てくるかもしれない。
またダートでみると、牡馬の時と違いMとの距離カテゴリでサンデーサイレンスが目立つ。
結果として
サンデーサイレンスの競馬界への影響がとてつもなく強い
サンデーサイレンスだけでも詳しく調べてみる価値はあるように思う。

コメント

タイトルとURLをコピーしました