Lean Baseball

No Engineering, No Baseball.

「アイツと似ている」野球選手をPythonでいい感じにスコア化してみた - 2020年注目の選手の特徴とは

2019年のプロ野球が終わり, セイバーメトリクスと分析・解析には良いシーズンになりました.

改めましてこんにちは. @shinyorkeと申します.

このエントリーでは,

  • セイバーメトリクスで「打者の類似性」を算出する方法論と実装例(なおPython)
  • メジャーリーグの2018年データを用いた類似性の例
  • 2020年からプレーする助っ人とか, これからメジャー挑戦するあの選手は!?

を打者の成績にフォーカスして紹介します.*1

なお, このエントリーはJX通信社 Advent Calendar 2019および, Pythonその4 Advent Calendar 2019の18日目となります.*2

免責事項

念の為お断りしておくとこの分析・解析結果は@shinyorke個人の見解であり, 現在および過去に在籍した組織・団体の見解・思想と関係ないことを予めお断りしておきます*3.

なお, 計算方法およびデータソースはPublicなものであります.

TL;DR(要約)

  • セイバーメトリクスおよびスポーツ統計の世界では「類似性スコア(Similarity Scores)」という指標があり, 通算成績を使うことにより選手同士の類似性を定量化できる
  • 類似性スコアの計算そのものはPython + Pandasでアッサリいける
  • 控えっぽい選手は何処へ行っても控えだし, 恵体タイプの日本人メジャーリーガーは恵体タイプのメジャーリーガーに似る可能性が高そう(こなみ)

スタメン

前半は類似性スコアの説明, 中盤はPythonでの実装方法(軽く), 後半に分析結果を紹介します.

類似性スコア #とは

すごく雑に言うと,

類似性を見たい選手を1000点とした場合, 比較対象の選手は何点になるか?

を見て類似性を確認する指標・スコアとなります.

(意外と言っちゃ失礼ですが)日本語のウィキペディアの説明そのままなのでこちらを見てもらうと良いかもです.*4

ja.wikipedia.org

ちなみに本家っぽい説明はこちらです.

www.baseball-reference.com

例のごとく, (セイバーメトリクスの生みの親であり神様である)ビル・ジェームズ氏により提唱され, 現在でも成績予測システムなどの一部で用いられている考え方となります.

基本的な考え方は減点法となっており,

  • 本人と瓜二つであれば1000点
  • 成績・指標を比較し, 差分に当たる部分を減算していく
  • 最後にポジションで補正.

という決め方をしていきます.

なお, 減算ポイント(差がある毎に引いていくポイント)はこんな感じです by 野手の場合.

指標 減点ポイント
試合数(G) 20
打数(AB) 75
得点(R) 10
安打(H) 15
二塁打(2B) 5
三塁打(3B) 4
本塁打(HR) 2
打点(RBI) 10
四球(BB) 25
三振(SO) 150
盗塁(SB) 20
打率(AVG) 0.001
長打率(SLG) 0.002

差分の分だけ引いていく感じです.

そしてポジション補正はこちら.

ポジション 補正ポイント
捕手(C) 240
遊撃手(SS) 168
二塁手(2B) 132
三塁手(3B) 84
外野手(OF)*5 48
一塁手(1B) 12
指名打者(DH), 投手(P) 0

「守備が重要なポジションは高めに, そうでもないポジションは低めに」という補正を入れることで単純に打てばいい・走ればいい, の要素を丸めています. *6

例えば打率.310本塁打15本60打点という野手がいたとして,

  • これが捕手や遊撃手だったら超優秀な選手になる(守備で稼ぐポジションで打てるのは万能扱い)
  • 一方, 打撃で貢献すべき一塁や指名打者の場合, 「もっと長打を打てや〜!」的な感じになる

と思うんですよ, それを表現するためにスコアで差をつけるようにしています.

Pythonで算出する

続いて算出方法です.

データはMLBの2018年までの通算成績を使います.*7

今回は(ないしは今回も*8)「Analyzing Baseball Data with R」を参考に独自に組みました.*9

事前準備として,「打者の通算成績」をSean Lahman Databaseから用意しましょう(前処理とかは面倒なので割愛).

f:id:shinyorke:20191217122718p:plain
事前にポジション補正(Value.POS)もやっておく

なお, 今回使う環境は

  • Python 3.7
  • Pandas*10
  • Jupyter notebook
  • plotly

となります.

サンプルコード(計算)

算出そのものはpandasのapplyを上手く使ってやります.

事前に関数を定義した後,

# Similarity Scores

import math

BASE_SIM_SCORE = 1000
SIM_PARAMATER = {
    'G': 20,
    'AB': 75,
    'R': 10,
    'H': 15,
    '2B': 5,
    '3B': 4,
    'HR': 2,
    'RBI': 10,
    'BB': 25,
    'SO': 150,
    'SB': 20,
    'AVG': 0.001,
    'SLG': 0.002
}

def similar(df: pd.DataFrame, player_id, head_cnt=10, params=SIM_PARAMATER) -> pd.DataFrame:
    _df = df.copy(deep=True)
    
    def calc_sim_score(row: pd.Series, player: dict) -> float:
        score = BASE_SIM_SCORE
        for k, param in params.items():
            # 各成績を比較(選手X - モデルの選手, の絶対値) / 定数
            score -= math.floor(abs(row[k] - player[k]) / param)
        score -= abs(row['Value.POS'] - player['Value.POS'])
        return score
    
    p = df.query(f'playerID=="{player_id}"')
    if len(p) == 1:
        dict_p = p.to_dict('records')[0]
        _df['sim_score'] = _df.apply(calc_sim_score, axis=1, player=dict_p)
        return _df.sort_values(['sim_score', 'playerID'], ascending=[False, True]).head(head_cnt)        
    else:
        raise Exception(f'player not found:"{player_id}"')
    

pandasでエイッとやりましょう.

# Similarity Scores DataFrame
def similar_df(name: str, count=6, params=SIM_PARAMATER) -> pd.DataFrame:
    _id = get_player_id(name=name)
    _df_sim = similar(df_c_totals, player_id=_id, head_cnt=count, params=params)
    _df_sim['BB/SO'] = _df_sim['BB'] / _df_sim['SO']
    return _df_sim[['sim_score', 'name', 'playerID', 'POS', 'G', 'AB', 'H', '2B', '3B', 'HR', 'R', 'RBI', 'BB', 'SO', 'SB', 'BB/SO', 'AVG', 'OBP', 'SLG', 'OPS']]

これであとは選手名を渡すだけで算出できます(例はイチロー).

# 先頭が本人になるので, 上位10件表示は11を指定
_df_ichi_sim = similar_df('Ichiro Suzuki', count=11)

サンプルコード(可視化)

今回はグラフで書くより普通にTableの方が良いだろうということでplotlyでテーブルを書く方法で可視化しました.

選手名とスコアに参考成績を出しています.

import plotly.graph_objects as go

def show_table(df: pd.DataFrame, header=['name', 'sim_score', 'POS', 'AVG', 'H', 'HR', 'RBI', 'OBP', 'SLG', 'OPS']):
    fig = go.Figure(
        data=[
            go.Table(
                header=dict(values=header), 
                cells=dict(values=[df[col].values for col in header])
            )
        ]
    )
    fig.update_layout(
        autosize=False,
        width=1400,
        height=320,
        margin=go.layout.Margin(
            l=50,
            r=50,
            b=20,
            t=20,
            pad=4
        ),
    )    
    fig.show()

先ほどのスコア算出・可視化をまとめてやるとこうなります.

# 先頭が本人になるので, 上位10件表示は11を指定
_df_ichi_sim = similar_df('Ichiro Suzuki', count=11)
show_table(_df_ichi_sim)

そしてこんな感じでテーブルが出てきます.

f:id:shinyorke:20191217123607p:plain
Ichiro Suzukiの類似性スコア

842点を出したケニー・ロフトン(Kenny Lofton)はたしかにイチローっぽい俊足巧打で四球も三振も少ない一番バッタータイプな外野手なのでだいぶいい感じっぽいですね!*11

2020年に移籍した選手で見てみる

イチロー氏でいい感じに素振りができたのでここから本命の分析へ.

(まだ確定していない選手もいますが)今年は,

  • ガチのメジャーリーグで活躍したツワモノが2020年の助っ人として来日
  • プロ野球(NPB)および侍JAPANで活躍した主軸が遠くメジャーリーグの舞台へ

という点で移籍が活発化しています.

2018年時点でのデータで「他の誰に似ているか」を類似性スコアで見てみました.

メジャーからやってくる強い選手

今年の注目といえばやっぱりガチ・メジャーリーガーのアダム・ジョーンズそしてワールドシリーズ制覇したばっかりのナショナルズからやってくるヘラルド・パーラですねと.

類似性グラフはこちらです.

f:id:shinyorke:20191217115209p:plain
注目新助っ人二人の類似性

アダム・ジョーンズ

長年オリオールズの不動のセンターで昨年はダイヤモンドバックスでプレー(つまり平野と同僚).

www.47news.jp

そんなアダム・ジョーンズ(略称アダジョ*12)はざっくりで言うと,

  • 全盛期でシーズン30本塁打を打つ打力&足が速い(が盗塁少ない)*13
  • かつては守備の名手, 基本的にセンターだが外野両翼守れる

という特徴があります.

そんなアダジョのスコアがこちら

f:id:shinyorke:20191217134654p:plain
ウェルズ, ペンス, ケンプなど強い外野手が並ぶ

現役(もしくは引退して間もない)選手だと,

が近いことがわかります.

実はこれホント近い選手の集まりで,

  • いずれも全盛期は本塁打30本(近く)打てる, 足もそれなりに速い強打のセンターもしくはライト. *14
  • 3人ともオールスター・クラスかつ, 高額の長期契約を勝ち取っている, ちなみにアダジョも同様.
  • なお, 契約後は死刑囚衰えで(ry

という点で似ています, ちなみに10位のジャスティン・アップトン(Justin Upton, 919点)は大谷翔平の同僚(レフト)です.

アダジョは来年35歳で(おそらく期待されている)守備や長打力が衰えそうな時期かなっていうのが正直な所ありますが.

これだけ大物と似てるのであれば期待していいかもしれません, 33本塁打4盗塁ぐらいは行けるのではないでしょうか(適当).*15

ヘラルド・パーラ

元祖ベイビーシャーク, としてファンの間ではお馴染みな選手.

full-count.jp

ポジション的には左打ちの外野手で, ジャイアンツでは(おそらく)亀井選手っぽい起用方法になりそうです.

そんなベイビーシャークさんのスコアがこちら.

f:id:shinyorke:20191217140643p:plain
守備走塁上手い4人目の外野手系が並ぶ?

守備固め・代打で存在感を出しナショナルズの世界一に貢献している選手ではありますが, 若干小粒感が否めないラインナップです...

なぜなら, 自分が知らない選手&(おそらく)第4の外野手*16だらけ!

唯一把握してたエンジェル・パガン(Angel Pagan, 946点)も似たような選手でした.

今シーズンは(37歳という年齢でありながら)キャリア的に良い成績残した亀井選手のスタメンを奪取できるかが見ものだと思います.*17

これからメジャーに行く選手

といえばやっぱり筒香選手(レイズ)と秋山選手(未定)ですね.

気になるので見てみました.

ただ日本のみプレーの選手については,

  • 当然MLB2018データに二人はいないので, 現時点の通算成績を手動でアノテーションして成績入れた(公式記録を参考に)
  • 2019年までの日本通算成績と2018データの比較かつ, 何よりも「MLBとNPBを等価で扱っている」のであくまでお遊び程度*18

という感じなのであくまでお遊びとしてお楽しみください.

というわけで数字はこちらです.

f:id:shinyorke:20191217115515p:plain
筒香選手と秋山選手

筒香嘉智

先日タンパベイ・レイズとの契約が決まりました&起用方法は「三塁・レフト・DH」を行ったり来たりが予想されます.*19

www3.nhk.or.jp

スコアを見てみると,

f:id:shinyorke:20191217141631p:plain
J.D.にハーパー, アレナドと強いやつが揃う

とリーグを代表する化け物が並んでいます, 特にJ.D.がイメージ一番近いかも.

守備が不安視されていますが, 間違いなく日本人では屈指のパワーと(三振多少多いですが)ボールを選べる選手ではあるのでレイズのニーズにあった活躍はしてくれそうな気がします.

あと, 軒並み体が大きい, 恵体選手が多いです.*20

秋山翔吾

最後に秋山選手です, ちなみにこの記事を執筆した12/17現在では所属未定となっています.

f:id:shinyorke:20191217142512p:plain
エルズベリーが一番イメージに近い?

秋山みたいなタイプはメジャーにいそうでいないのでスコアがちょっと低めです.

かつてレッドソックス不動の一番センターだった, ジャコビー・エルズベリー(Jacoby Ellsbury, 933点)の名前がありますがこれは確かに納得です, レッドソックス時代の全盛期だったら*21.

ただスコアも低いのと前例がなさすぎる気がするので暖かく見守りたいですね.

まとめ

というわけで今回はスポーツ, 野球の統計モデルを使って「アイツと似ている」を検証しました.

がこの方法の問題として,

  • 通算成績で見てるので「今」のスナップショットが見れない
  • 年齢による衰えなどが考慮されていない
  • 異なるポジション同士でも比較したくない?

という課題があります.

これらはいずれ少しずつ解いて何か面白いことができればと思います, あとやっぱPython道具として便利.

というわけでこのテーマでまた継続してできればと思います.

*1:投手編はいずれやりたい.

*2:と同時に「Python mini Hack-a-thon(#pyhack) #106」の成果発表で話したネタ(の完成版)です.

*3:スポーツ科学とも関係ありません. あくまでも公開情報を元に統計的に処理した情報と受け取ってください.

*4:余談ですが日本語ウィキペディアの野球記録・データ解説は結構詳しくて英語版と原則的に相違が無いです, たまに数式古かったりしますがその程度.

*5:3ポジション丸めてスコア化. センターの貢献度とか考えると弄りたいところですが少なくともオリジナルの考え方が3ポジションまとめてです.(これが守備指標とかだと当然分けることが多い)

*6:この考え方は類似性スコア以外の指標にも多かれ少なかれあります.

*7:ホントは2019といいたいところですが, Sean Lahmanで公開されていないので諦めました.

*8:RからPythonへお引越しの参考文献でもあります.

*9:コードは都合により, snippet以上のものは公開しません :bow:

*10:Pandasのいい感じな使い方はこのあたりが参考になります. 余談ですが今回はapply使ってます(map化するのには変数多くて心折れたので断念).

*11:ちなみにイチロー現役時代に引き合いに出やすい選手ではありました&もっとにていそうなトニー・グウィン(Tony Gwynn)が821点だったのは意外.

*12:日本のMLBファンの間での呼び名と認識してます, 主にTwitter界隈

*13:じゃあ走塁上手いかって言われると微妙ですがそこそこ二塁打多いので上手いのかな

*14:ギータぐらいのイメージで良いかも, ちなみにペンスはメインがライトで30本塁打超えの経験ありませんが似たタイプではあるので数えていいかなと.

*15:私の主観では2019年の成績を維持できたら御の字かなって気がします&守備はMLBでよく見る指標で定性評価よりも悪いので大きな期待はできないかも.

*16:外野って3ポジションだけじゃないですが, 察してください.

*17:亀井選手は明らかに第4外野手を超えた貢献している認識です.

*18:つまり, ちゃんとやるなら補正しろって話です.

*19:レイズは極端な守備シフトを敷くのとその関係で複数ポジション守れる選手が重宝される傾向にあります. ちなみに統計・データ分析をすごく活用している.

*20:3人とも身長190cm前後で体重が90kg以上. 公称値より.

*21:ヤンキース金銭闘争へ エルズベリーと残り年俸巡り - MLB : 日刊スポーツ