下校時刻

メモ、読んだ本のまとめメモ、考えたことのメモ、その他のメモなどが書いてあるブログです(twitter: @hoture6)

pandasでMLBのアウトカウント・ランナー状況別の得点期待値を計算する

こんにちは。

突然ですが、今日は野球の統計学において大切な指標である「得点期待値」を計算していきたいと思います。

得点期待値とは何か

得点期待値とは、「ある状況(アウト数・ランナー)において、その後どのくらい得点が入ることが期待できるか」を表す値です。たとえば、直感的に作った架空の例ですが、

  • 2アウト・ランナーなし:0.1点
  • 2アウト・ランナー2塁:0.5点
  • 0アウト・ランナー23塁:2.0点

という感じです。


意義

そもそもなぜ得点期待値などというもの計算する必要があるのでしょうか。そんなことをして何の意味があるのでしょうか。人はなぜ生きるのでしょうか。

野球チームの最終目標を思い出してみましょう。野球チームの目標は、たぶん優勝することです。優勝するためには、多くの試合に勝つ必要があります。試合に勝つためには、得点をとる必要があります。
つまり、野球チームにとって、得点を取ることが非常に重要です。そして、「現在の状況だと、どのくらい得点を取れることが期待できるのか」を表すのが得点期待値なのです。

もちろん、得点期待値を知ったからといって、得点がいっぱい取れるようになるわけではありません。ただ、「選手の価値」や「プレイの価値」を考える上で役に立ちます。

得点期待値から見るプレイの価値

あなたが応援しているチームの選手AとBが、それぞれ以下のプレイをしたとします。

  • A:「2アウト・ランナーなし」からヒットを打って、「2アウト・ランナー1塁」にした
  • B:「0アウト・ランナーなし」からヒットを打って、「0アウト・ランナー1塁」にした

どう思いますか。違いはアウトカウントだけなのですが、どちらかというとBのプレイの方をより賞賛したいのではないでしょうか。そして、その理由は「0アウト・ランナー1塁の方がなんとなく得点が入りそうな気がして嬉しいから」だと思います。

もちろん2アウト・ランナー1塁にしてくれたAもありがたいですし、実際そこから得点が入ることもよくあると思います。 ただ、なんとなく2アウトからではもう遅いのでは感がありますね。

以上の雑な議論をまとめると、上の例だと選手Bのプレイの方が得点の確率を高めており、ひいてはチームに貢献していそうだということになります。

この貢献度の違いを客観的に数値化できないものでしょうか。単に打率や出塁率長打率・打点などを考えるだけでは、2つのプレイはまったく同じように評価されてしまいます。

ここで、得点期待値が登場します。それぞれのプレイの価値を、

  • A:(2アウト・ランナー1塁の得点期待値) - (2アウト・ランナーなしの得点期待値)
  • B:(0アウト・ランナー1塁の得点期待値) - (0アウト・ランナーなしの得点期待値)

と評価します。つまり、そのプレイでどのくらい得点期待値が上がったかでプレイの価値を見るということです。これで、なんとなくいい感じで貢献度が評価できそうな気がしませんか(してください)。

直感的にも、「0アウト・ランナー1塁の期待感と0アウト・ランナーなしの期待感の差」の方が「2アウト・ランナー1塁の期待感と2アウト・ランナーなしの期待感の差」の方が大きそうですよね。

ということで、得点期待値を使うことで、以上のようなより状況に即したプレイの評価ができるようになります。

計算

それでは、実際に計算してみましょう。プログラミングや計算の詳細に興味がない人は適当に読み飛ばしてください。

計算はpythonのpandasというライブラリを使って行います。pandasは、python版のRとかExcelみたいなもので、非常に便利なのでぜひ使いましょう。

データはRetrosheetというサイトからいただきます。RetrosheetはMLBのすべての試合について、すべてのプレイの詳細を記録しているという意味不明なありがたすぎるサイトです。 ありがたくない点として、Retrosheetのプレイの記法が非常に難しいという点があります。

そこで、py-retrosheetという、Retrosheetを人間とかpythonが読める形に変換してくれるツールを使いましょう。 詳細は省きますが、readmeの通りに進めていけば、いい感じのcsvファイルができたり、いい感じでRDBにデータを入れられたりします。

以下がjupyter notebookのコードです。私はpythonの素人(かつpandasの素人(かつ統計の素人(かつ人生の素人)))なので、間違っていたり冗長なコードになっている可能性が高く、指摘をいただければ幸いです。 作業の方針や内容などはコード内のコメントに書いてあります。

結果

結果です。

0アウト 1アウト 2アウト
ランナーなし 0.554 0.283 0.109
1塁 0.921 0.548 0.238
2塁 1.164 0.714 0.342
3塁 1.441 0.976 0.378
1塁・2塁 1.528 0.944 0.459
1塁・3塁 1.837 1.206 0.522
2塁・3塁 2.043 1.435 0.608
満塁 2.376 1.603 0.804

なるほど〜。

各自、表を見ながらなるほど〜と思っていただければ幸いですが、一応簡単に考察してみます。

0アウトのヒットと2アウトのヒット

最初にあげた例

  • A:2アウト・ランナーなしからヒット → 2アウト・ランナー1塁
  • B:0アウト・ランナーなしからヒット → 0アウト・ランナー1塁

の価値を考えてみます。上記の表を見ながら得点期待値の変化を追ってみると、

  • A:0.109 → 0.238(+0.129)
  • B:0.554 → 0.921(+0.367)

となり、Bのプレイの方が(得点という観点からすると)3倍近くの価値があることがわかります。 つまり、非常に適当に言うと、先頭打者の出塁は2アウトからの出塁より3倍くらいありがたいということですね。

送りバント

例えば0アウト・ランナー1塁からの送りバントで1アウト・ランナー2塁にするとすると、得点期待値は0.921から0.714に下がってしまいます。

同様にいろいろな状況からの送りバントを考えると、すべての状況で得点期待値が大きく下がることがわかります(確認してみてください)。

もちろん、得点期待値からの議論で考慮に入れられていない要素もあるので、以上から送りバントに価値がないと判断するのは短絡的です。つまり、得点期待値では

  • すべての打者を平均的な実力として評価している(現在の打者より次の打者の方が良い打者ならばバントの価値があるかも)
  • 現在のスコア状況を無視している(1点取れば勝ちの状況なら得点期待値ではなく得点確率を考慮すべき)
  • バント失敗の確率がわからない(バントは100%成功するわけではない)

ので、実際に送りバントを試みる価値というのはわかりませんね。しかし、議論の出発点としては面白いと思います。

まとめ

pandasとRetrosheetを使って状況別の得点期待値を求めました。 次回から、今回求めた得点期待値を使ったり使わなかったりして、いろいろと野球の統計を調べていきたいと思います。

以上、よろしくお願いします。

参考文献