(80) 野球選手を測ってみる 2016年版

投稿者: | 2016年11月12日

2,937 views

この記事は最終更新から 1812日 が経過しています。

姉妹サイト Octaveやってみる! で2014年に遊んでみた (32) 野球選手の成績を主成分分析 と同じことを Pythonでもやってみる。

対象データは 2016年のプロ野球セパ両リーグのレギュラークラス 55人の打者成績とする。

データはYahoo!さんのサイト(↑)からお借りしました。m(_ _)m

1. テーマは野球選手の総合評価

個人的には、何でもそつなくこなす選手が好きです。
蓑田選手(阪急)
松永選手(阪急)
前田選手(広島)
などなど、本塁打、打点、打率などの単一項目での評価ではなく、
タイトルホルダーじゃないけどスゴイ選手!
の度合が計測できる、そんな物差しを見つけてくれることを楽しみにやってみます。

2. 計算手順

主成分分析の対象とする変量(打者成績項目)は、以下の9項目とする。
打席数、安打、本塁打、塁打数、打点、得点、三振、四球、盗塁

前述の打者成績をCSVファイルに保存しておき、これをPythonでロードする。
※今回はscikit-learnを使わずにPCAしてみる。

>>> import numpy as np
>>> X = np.loadtxt('in_data.csv', delimiter=',')
>>> X
array([[ 576.,  168.,   23.,  271.,   75.,   96.,   67.,   81.,   13.],
       [ 528.,  156.,   29.,  285.,   95.,   76.,   79.,   53.,   16.],
       [ 561.,  151.,   44.,  319.,  110.,   89.,  105.,   87.,    0.],
       [ 640.,  181.,   13.,  248.,   56.,   92.,  106.,   40.,   13.],
       [ 523.,  141.,   11.,  205.,   59.,   52.,   78.,   61.,    0.],
       [ 590.,  146.,   38.,  292.,  102.,  102.,  101.,   97.,   30.],
       [ 576.,  160.,   25.,  267.,   81.,   58.,   83.,   38.,    1.],
       [ 458.,  127.,    1.,  154.,   32.,   48.,   31.,   34.,    3.],
       [ 513.,  136.,   19.,  220.,  101.,   66.,  101.,   54.,    0.],
       [ 607.,  155.,    0.,  179.,   39.,   74.,   66.,   63.,    7.],
       [ 566.,  157.,    1.,  183.,   38.,   38.,   98.,   22.,    2.],
       [ 656.,  175.,    3.,  229.,   27.,   80.,   69.,   46.,   26.],
       [ 652.,  162.,   20.,  268.,   90.,   98.,  107.,   84.,   23.],
       [ 522.,  131.,   11.,  191.,   49.,   80.,   93.,   38.,   19.],
       [ 618.,  163.,   11.,  232.,   42.,   58.,   78.,   33.,    8.],
       [ 530.,  136.,    8.,  193.,   65.,   48.,  109.,   27.,    5.],
       [ 471.,  114.,   22.,  202.,   68.,   63.,   68.,   44.,    1.],
       [ 450.,  108.,   18.,  190.,   56.,   69.,  110.,   49.,   26.],
       [ 537.,  123.,   31.,  236.,   96.,   64.,  116.,   72.,    0.],
       [ 679.,  154.,   13.,  216.,   39.,  102.,  119.,   77.,   28.],
       [ 518.,  127.,   34.,  258.,   95.,   66.,   75.,   24.,    0.],
       [ 465.,  109.,   24.,  205.,   68.,   48.,  106.,   39.,    0.],
       [ 554.,  127.,   22.,  213.,   79.,   58.,  130.,   48.,    2.],
       [ 507.,  116.,    6.,  165.,   46.,   38.,   69.,   27.,    1.],
       [ 494.,  103.,   14.,  171.,   73.,   61.,   89.,   72.,    4.],
       [ 533.,  106.,    7.,  145.,   36.,   49.,   80.,   75.,   13.],
       [ 458.,   81.,    4.,  107.,   35.,   27.,   76.,   36.,    2.],
       [ 607.,  178.,    8.,  242.,   69.,   74.,   64.,   68.,   12.],
       [ 593.,  155.,    5.,  196.,   43.,   76.,  113.,   73.,   41.],
       [ 611.,  172.,   24.,  284.,   82.,   73.,  108.,   38.,    8.],
       [ 616.,  163.,   17.,  240.,   70.,   79.,   84.,   75.,   53.],
       [ 536.,  131.,   18.,  224.,   73.,   82.,   97.,  100.,   23.],
       [ 605.,  169.,   18.,  242.,  106.,   62.,   53.,   38.,    3.],
       [ 671.,  171.,   11.,  244.,   62.,   98.,  103.,   77.,   18.],
       [ 555.,  145.,   14.,  213.,   61.,   66.,  121.,   42.,    5.],
       [ 612.,  140.,    7.,  184.,   50.,   69.,   53.,   99.,    6.],
       [ 583.,  143.,    6.,  195.,   61.,   62.,   56.,   50.,    3.],
       [ 513.,  129.,   20.,  214.,   76.,   56.,  105.,   47.,    5.],
       [ 570.,  139.,   24.,  238.,   92.,   81.,   89.,   64.,    0.],
       [ 569.,  133.,    3.,  176.,   41.,   52.,   87.,   83.,    0.],
       [ 481.,  118.,    7.,  173.,   40.,   56.,   95.,   30.,   11.],
       [ 497.,  116.,    2.,  141.,   43.,   39.,   49.,   61.,    1.],
       [ 488.,  110.,    1.,  130.,   34.,   51.,   53.,   42.,    6.],
       [ 626.,  147.,    2.,  169.,   53.,   61.,   56.,   69.,   22.],
       [ 520.,  122.,    1.,  143.,   33.,   64.,   69.,   40.,   53.],
       [ 589.,  137.,   27.,  247.,   88.,   74.,  123.,   58.,    2.],
       [ 449.,  108.,    0.,  131.,   46.,   27.,   44.,   19.,    1.],
       [ 610.,  142.,    2.,  178.,   33.,   63.,   55.,   56.,   16.],
       [ 598.,  144.,   39.,  282.,   97.,   71.,  138.,   44.,    0.],
       [ 609.,  142.,   27.,  256.,   85.,   79.,  141.,   48.,    6.],
       [ 583.,  129.,   35.,  260.,  103.,   73.,  148.,   59.,    1.],
       [ 485.,  106.,    6.,  145.,   35.,   44.,   49.,   46.,    7.],
       [ 624.,  142.,   25.,  245.,  110.,   61.,  126.,   47.,    2.],
       [ 590.,  122.,   10.,  184.,   56.,   74.,   86.,   47.,    8.],
       [ 600.,  115.,    0.,  127.,   28.,   66.,  117.,   63.,   23.]])

打者項目によって数値の範囲にばらつきがあるため、平均0、分散1に標準化しておく。
でも、項目によって価値がだいぶ違うものもあるので、項目別のレンジ調整が必要かも…

>>> Xm = np.broadcast_to(X.mean(axis=0), X.shape)
>>> Xs = np.broadcast_to(X.std(axis=0),  X.shape)
>>> Xv = (X - Xm) / Xs

固有ベクトル(v), 固有値(l)を求める。

>>> R1  = np.corrcoef(Xv.T)
>>> l,v = np.linalg.eigh(R1)

ランクが見やすいように寄与率を算出する。

>>> l / l.sum() * 100
array([  0.08933219,   1.01050674,   1.50297613,   2.19603783,
         6.06787656,   8.22801916,  11.12005857,  23.43222355,  46.35296927])

寄与率が大きいものは、
第1主成分 (8) 46.4%
第2主成分 (7) 23.4%
第3主成分 (6) 11.1%
ここまでで 80.9%

選んだ3種類の主成分スコアを算出する。

>>> scr_8  = Xv * np.broadcast_to(v[::,8:9].T, X.shape)
>>> scr_7  = Xv * np.broadcast_to(v[::,7:8].T, X.shape)
>>> scr_6  = Xv * np.broadcast_to(v[::,6:7].T, X.shape)

3. 結果を見てみる。

第1主成分から第3主成分まで、作ってくれた物差しは以下のようなもの。
※直観的に野球成績と比較しやすいように正負の向きを逆にした。

第1主成分 (46.4%)

ケガなく出場し、安打打ちまくり、デカいのも打て、よく本塁に帰ってくる。
いわゆるオールマイティな選手
↓を見ると、確かに誰もがスゴイと納得する選手が上位に並んでいる。

第2主成分 (23.4%)

出場機会は少ないが、本塁打をよく打ち打点を稼ぐ。でも早打ち&選球眼イマイチで鈍足。
いわゆる当たれば飛ぶ一発屋タイプ
↓を見ると、確かに一発屋の助っ人外国人選手が上位に並んでいる。

第3主成分 (11.1%)

非力であまりヒットを打たないが、よく四球を選んで出塁し、盗塁で相手守備をかき乱す。
いわゆる???
難しいなぁ、リードオフマンタイプでもないしなぁ、巨人鈴木選手タイプか?
寄与率11%だからこんなもんか…

全55人を各物差しで測った結果は以下の通り。

x. 備忘録

リードオフマン物差しが出来なかったのが残念だ。
変量にリードオフマンの特徴を表すような項目を追加する必要がありそうだ。


コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です