サイアーラインの可視化（＋α）

# 1.まとめ
* 競走馬のサイアーラインをネットワーク図で可視化してみた。
* 知っている馬の名前が出てきてうれしかった。
* もう少し昔まで（できれば祖先の３頭まで）さかのぼりたい

# 2. はじめに
* 宮本輝の[優駿](https://www.amazon.co.jp/%E5%84%AA%E9%A7%BF%E3%80%88%E4%B8%8A%E3%80%89-%E6%96%B0%E6%BD%AE%E6%96%87%E5%BA%AB-%E5%AE%AE%E6%9C%AC-%E8%BC%9D/dp/4101307067)や[世界の名馬](https://www.amazon.co.jp/%E4%B8%96%E7%95%8C%E3%81%AE%E5%90%8D%E9%A6%AC%E2%80%95%E3%82%BB%E3%83%B3%E3%83%88%E3%82%B5%E3%82%A4%E3%83%A2%E3%83%B3%E3%81%8B%E3%82%89%E3%82%B1%E3%83%AB%E3%82%BD%E3%81%BE%E3%81%A7-1970%E5%B9%B4-%E5%8E%9F%E7%94%B0-%E4%BF%8A%E6%B2%BB/dp/B000J92ZVE)を小学校で読んで以来サイアーラインにあこがれていた。ダビスタにもはまり夜を徹してゲームしてたりした。

* 個人的には[マンノウォー](https://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%B3%E3%83%8E%E3%82%A6%E3%82%A9%E3%83%BC)と[ネイティブダンサー](https://ja.wikipedia.org/wiki/%E3%83%8D%E3%82%A4%E3%83%86%E3%82%A3%E3%83%B4%E3%83%80%E3%83%B3%E3%82%B5%E3%83%BC)と[セクレタリアト](https://ja.wikipedia.org/wiki/%E3%82%BB%E3%82%AF%E3%83%AC%E3%82%BF%E3%83%AA%E3%82%A2%E3%83%88)が好きです。

* 上記の「優駿」に書いてますが、世界中の競走馬の父系をたどると、たった３頭の馬につながる。現在の競馬（サラブレッド）は17世紀にはじまったので、その家系図をたどることができ、[サイアーライン](https://ja.wikipedia.org/wiki/%E3%82%B5%E3%82%A4%E3%82%A2%E3%83%BC%E3%83%A9%E3%82%A4%E3%83%B3)というものがあるとのこと。


# 3.サイアーラインとは
* [説明記事](https://ja.wikipedia.org/wiki/%E3%82%B5%E3%82%A4%E3%82%A2%E3%83%BC%E3%83%A9%E3%82%A4%E3%83%B3)を参照。
* どの馬にも、父をさかのぼると３頭の血のみが受け継がれているなんて、ロマンがある！ぜひこれをたどって可視化したい！

# 4. データ
* ネット上にもいろいろ情報が散らばっているけど、まとまってデータをとれたのが(JRDB)[http://www.jrdb.com/]の有料会員の競馬データ。
* 血統以外にもオッズデータ、調教師データ、騎手データ、開催データなどこまかくひろく色々情報があるのでそれはそれで面白そうだが今回は割愛。
* 血統データの項目は次のような感じ。

```html
馬名
性別コード
毛色コード
馬記号コード
血統情報
  父馬名
  母馬名
  母父馬名
生年月日
父馬生年
母馬生年
母父馬生年
馬主名
馬主会コード
生産者名
産地名
登録抹消フラグ
データ年月日
父系統コード
母父系統コード   
```

このうち、馬名、父馬名、母馬名、母父馬名をとれればサイアーライン（＋α）が可視化できるだろう、ということで抽出。可視化は例のようにpyvisを利用させてもらう。
まずは上記のデータをBigQueryに投入。
カラム名がひどくてすみません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/663bdb1d-94e5-8ca3-f5fe-d8519cbca7d1.png)


```sql
#_1=馬名、5_=父馬、6_=母馬、7_=母父馬
SELECT _1,_5,_6,_7 FROM `racehorse.racehorse.ukc`
WHERE _7 LIKE "%メジロマックイーン%" AND _5 LIKE "%ステイ%"
GROUP BY _1,_5,_6,_7
ORDER BY _1 ASC
```
ちゃんと、ゴールドシップとオルフェーブルが入ってますな。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/998cdaf1-b844-3e86-b3ea-682fac2c3410.png)

さて、以下で

```sql
SELECT _1,_5 FROM `racehorse.racehorse.ukc`
GROUP BY _1,_5
UNION DISTINCT
SELECT _1,_6 FROM `racehorse.racehorse.ukc`
GROUP BY _1,_6
UNION DISTINCT
SELECT _6,_7 FROM `racehorse.racehorse.ukc`
GROUP BY _6,_7

```


対象馬←父
対象馬←母
母←母父
のedgeが抽出できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/3a5599e5-0ebe-18d5-564a-3da3d1ec5e16.png)


## 4.1 edgeデータ作成

```python

from google.cloud import bigquery
project_id = 'racehorse'

client = bigquery.Client(project=project_id)
def getlinedata():

    #search_term = query
    # 実行するクエリ
    query3 =  """
    SELECT _1,_5 FROM `racehorse.racehorse.ukc`
    GROUP BY _1,_5
    UNION DISTINCT
    SELECT _1,_6 FROM `racehorse.racehorse.ukc`
    GROUP BY _1,_6
    UNION DISTINCT
    SELECT _6,_7 FROM `racehorse.racehorse.ukc`
    GROUP BY _6,_7
         """

    # メソッドに`to_dataframe()`をつけるとpd.DataFrameで結果を受け取れる
    all_df = client.query(query3).to_dataframe()


    return all_df


frame = getlinedata()
frame.rename(columns={"_5":"source","_1":"target"},inplace=True)

```

## 4.2networkxに入れる。

```python
import networkx as nx
G = nx.from_pandas_edgelist(frame,create_using=nx.DiGraph())


eigen_centrality = nx.eigenvector_centrality_numpy(G)
bet_centrality = nx.betweenness_centrality(G,k=10)
degree_centrality = nx.degree_centrality(G)
degree_coefficient = nx.clustering(G)
```

## 4.3 次数中心上位を見る

```python
pd.DataFrame([degree_centrality]).T.sort_values(by=0,ascending=False).head(20)
```

* 知ってる名前が。キングカメハメハが１位。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/49483c1e-1f34-8f28-109a-e922d63958a5.png)



## 4.4 絞りこみ後、pyvisに入れる
* 全員いれるとメモリが足りずクラッシュしたので、次数中心性上位のみを入れる。

```python
degree_filter = pd.DataFrame.from_dict(degree_centrality.items()).pipe(lambda df:df[df[1]>0.01])[0].tolist()
frame2 = frame[frame['source'].isin(degree_filter)]

G2 = nx.from_pandas_edgelist(frame2,create_using=nx.DiGraph())
```

```python
#!pip install pyvis #最初に実行

from pyvis.network import Network
pyvis_G = Network()
pyvis_G.from_nx(G)
pyvis_G.show("mygraph.html")

```



# 5.可視化結果
pyvisでやりたかったけど、重すぎてダメだっため、急遽gephiを使うことに。しかも2022年に[ソフトウェアが更新されていた](https://github.com/gephi/gephi/wiki/Releases)。５年前の更新が最後だったので、これはこれで差分を要確認
１個のノード＝１頭の馬。ノードの大きさ＝次数（出次数＝子供が多い）に比例して、馬の名前が大きく表示される。色の違い＝グループの違い（modularity）。考察は別途。ちょっと見るだけでもなかなか面白い。フジキセキの位置がおかしい気がするけど、サンデーサイレンスのすごさが分かる。

* [全体図(pdf)](https://storage.googleapis.com/sireline/Untitled.pdf)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/520f1e66-8299-3428-8144-fb24a009a90f.png)



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/3e46f87d-bfe0-22cb-c524-1c70e462ec35.png)



主要馬のグルーピング（上記の色分け）

|グループ|馬名|
|:----|:----|
|0|ハービンジャー、ダンカーク、ルーラーシップ、マジェスティックウォリアー、サンデーサイレンス、エルコンドルパサー、アグネスタキオン、クロフネ、ファルブラヴ、ジャングルポケット、チチカステナンゴ、シンボリクリスエス、ウォーエンブレム、ローエングリン、キングカメハメハ、カンパニー、トーセンジョーダン、エイシンフラッシュ、モーリス、ストロングリターン、エピファネイア、ノヴェリスト、タートルボウル|
|1|キンシャサノキセキ、トニービン、フジキセキ|
|2|オンファイア、ワークフォース、フレンチデピュティ|
|3|ヘニーヒューズ、アルデバラン、ケイムホーム、ヨハネスブルグ、エンパイアメーカー、バゴ、ルールオブロー、バトルプラン、ケープブランコ|
|4|ダノンシャンティ、ロックオヴジブラルタル、ブラックタイド|
|5|アドマイヤムーン、パイロ、ファンタスティックライト、キングズベスト、ストーミングホーム、フリオーソ、モンテロッソ|
|6|スクリーンヒーロー、マツリダゴッホ、ドリームジャーニー、コンデュイット、ナカヤマフェスタ、アイルハヴアナザー、ステイゴールド、ショウナンカンプ、タイムパラドックス、ロージズインメイ、ゴールドシップ|
|7|ディープブリランテ、トーセンホマレボシ、リアルインパクト|
|14|リアルシャダイ|
|15|ホリスキー、タヤスツヨシ、エアジハード|
|16|バブルガムフェロー|
|19|カーリアン、シルヴァーチャーム|
|22|モガミ、アスワン、シンボリルドルフ、シャーディー|
|23|パークリージェント、タイトスポット、ロドリゴデトリアーノ|
|24|ミスタープロスペクター、ブレイヴェストローマン、トウショウボーイ、ロイヤルスキー、ダイナガリバー、アジュディケーティング、リズム、ウイニングチケット、エイシンサンディ|
|25|ダンスインザダーク|
|27|デュラブ、ラストタイクーン、サクラチトセオー、タバスコキャット|
|30|シアトルスルー、ヌレイエフ、ストームキャット|
|31|オジジアン、グルームダンサー、デザートキング|
|33|タマモクロス、ゴールデンフェザント、ディアブロ、スターオヴコジーン、スターオブコジーン、ペンタイア、サニーブライアン|
|34|ゴーンウェスト、キングマンボ|
|35|シーキングザゴールド、フォーティナイナー、デヒア、ボストンハーバー、コロナドズクエスト、カリズマティック|
|36|ラッキーソヴリン、サッカーボーイ、ティッカネン、ロイヤルタッチ|
|37|ダンジグ、アフリート、ウォーニング|
|39|ニホンピロウイナー、アドマイヤベガ、アドマイヤボス|
|40|ピルサドスキー|
|41|ブライアンズタイム|
|43|マルゼンスキー、サクラユタカオー、マイニング、サンシャインフォーエヴァー、カコイーシーズ、サクラローレル、サクラプレジデント|
|44|キンググローリアス、チーフベアハート、スクワートルスクワート|
|45|ジャイアンツコーズウェイ、ディープインパクト、ロードカナロア、ドゥラメンテ、オルフェーヴル|
|46|ソヴィエトスター、メジロマックイーン、メジロライアン、ホワイトマズル|
|47|ブラックタイアフェアー、ジョリーズヘイロー、アッミラーレ|
|48|サンダーガルチ|
|50|クリエイター、ジェイドロバリー、ナリタトップロード|
|51|ウッドマン、ヘクタープロテクター、ナリタブライアン|
|52|シアトルダンサー２、アンバーシャダイ、バンブーアトラス、クリスタルグリッターズ、ミスターシービー、ダンシングブレーヴ、エブロス、スキャン、リンドシェーバー、ハンセル、エルハーブ、サマーサスピション|
|53|ジェネラス|
|54|クリミナルタイプ、オペラハウス、トウカイテイオー、ゼンノエルシド|
|55|スリルショー、ヤマニンゼファー、ミシル、ティンバーカントリー|
|56|ノーザンテースト、ミルジョージ、アレミロード、ドクターデヴィアス、ジェニュイン、フサイチコンコルド、ゴールドヘイロー、フサイチソニック|
|58|シャンハイ、ブラックタキシード|
|60|アラジ|
|62|コマンダーインチーフ、テンビー、マヤノトップガン、キングヘイロー、オース、アグネスフライト、グランデラ、ムーンバラッド、アドマイヤジャパン|
|64|ビワハヤヒデ、タイキブリザード、マーベラスサンデー|
|65|トワイニング、スウェプトオーヴァーボード|
|66|サクラバクシンオー、エンドスウィープ|
|68|ラムタラ、タイキシャトル、アルカセット|
|70|スペシャルウィーク|
|72|グラスワンダー|
|73|パラダイスクリーク、リーチザクラウン|
|74|ブラックホーク、ストラヴィンスキー|
|75|エリシオ、クロコルージュ、キャプテンスティーヴ|
|76|カーネギー|
|77|カジノドライヴ、アグネスデジタル|
|78|ソングオブウインド、メイショウオウドウ、ミラクルアドマイヤ、アドマイヤコジーン、ニューイングランド、アドマイヤマックス、オレハマッテルゼ、リンカーン、サムライハート|
|79|タニノギムレット、ベルシャザール|
|80|テイエムオペラオー|
|81|ソウルオブザマター、グランプリボス|
|82|マイネルラヴ|
|84|ヴィクトワールピサ、エーピーインディ、フサイチペガサス、ゴールドアリュール、デュランダル、ネオユニヴァース、ゼンノロブロイ、ハーツクライ、ダイワメジャー、ジャスタウェイ|
|85|シニスターミニスター、メイショウサムソン、メイショウドトウ、マリエンバード、プリサイスエンド、スタテューオブリバティ、メイショウボーラー、フォーティーナイナーズサン、トゥザグローリー|
|96|サドラーズウェルズ、デインヒル|
|97|ディープスカイ、マンハッタンカフェ、キズナ|
|98|シアトリカル、アサティス、カリスタグローリ、ワイルドラッシュ、サウスヴィグラス、スキャターザゴールド、スズカマンボ、スズカフェニックス|
|99|ファスリエフ、スターリングローズ、カネヒキリ、ヴァーミリアン、スマートファルコン、ベーカバド|


# 6.次にやること
* 全部可視化するのが大変なので、純粋にサイアーラインまでとか、主要馬などに絞る機能が欲しい
* 現状、ノードの大きさは子供の多さ（次数）でつけているけど、色やノードの大きさで何かを表したい（勝利数とか、父系名とか。余談ですがミスタープロスペクター系ってできたんですね。）
* JRDBのデータが1999年までなので、それ以前の情報をネット上で探してとってきて追加したい。
* 時系列に並べたい
* ウェブアプリ化したい。[少し作れた](https://sireline.vercel.app/)
* データが一部おかしいのを発見。①同じ名前の馬が存在すると１かたまりになってしまう（ex:「キズナ」）。生年月日と性別との組み合わせで分ける必要あり。
* 親がノード中にいるのに、リンクが張ってない馬がいる（ex:トウカイテイオー-シンボリルドルフ）。１９９９年より前のデータがないためのエラーのようなのでデータの蓄積を続ける。