概要
野球が好きなので、打順の最適な組み方をついつい考えてしまいます。
ある検証で「強打者と弱い打者を交互に並べる」よりも「強打者を下位打線に固める」方が得点が入りやすいという結果が出たというのを知り、単純化したモデルで検証してみようと思い試してみました。
本格的な検証ではないので、Rubyを使って何か簡単な検証や計算を行ってみたいという人に大雑把な流れだけわかってもらえれば嬉しいです。
前提条件
- 3割打者5人と2割打者4人の2タイプを用意
- 打者は凡打か単打のみを打つ
- 凡打においてランナーは進塁せず、3連打で1点が入る
- 3連打以上では安打のたびに1得点を追加
- エラーや四死球は簡略化のため考慮しない
- 盗塁や送りバントはセイバーメトリクスで推奨されないので行わない
- 1万試合回して合計得点を競う
この超簡略化した野球で2タイプの打者の打順を入れ替えて、どれだけ得点が入るかを検証します。ただ四死球と長打を全て排除するのはあまりにも酷なので、あとでそれらを考慮したコードも紹介していきます。
打順の組み方は
- 上位5人に3割打者を固める
- 3割打者と2割打者を交互におく
- 3割打者を5-9番の下位に固める
の3種類とします。
変数を宣言
#1-9番の打者の打順を記録した配列
average=[0.3,0.3,0.3,0.3,0.3,0.2,0.2,0.2,0.2]
#合計得点
sumScore=0
#打席に立っている打者の打順
batter=1
#アウトカウント
outCount=0
#塁上のランナーの数
runner=0
#アウトカウント
iningCount=0
1イニングを終わらせてみる
loop {
hit = rand(1..100)
hit = hit/100.0
#乱数を使って単打か凡打を記録
if hit <= average[batter-1]
#走者を一人増やす
runner+=1
if runner>=3
#走者が2人以上たまっていたらランナーを本塁に返す
runner=2
sumScore+=1
end
else
#凡打なのでアウトカウントを増やすだけ
outCount+=1
if outCount == 3
#3アウトチェンジしてループを抜ける
runner=0
outCount=0
break
end
end
#次のバッターに交代
batter+=1
#9番打者を打ち終わったら一番に戻る
batter = (batter-1)%9 + 1
}
1万試合を回してみる
1万試合なので90000イニング繰り返して、何点入るかを検証します。ただ9万回回すのではなく、9回が終わったら打順を1番に戻す処理を忘れないようにします。
90000.times {
iningCount+=1
loop {
hit = rand(1..100)
hit = hit/100.0
#乱数を使って単打か凡打を記録
if hit <= average[batter-1]
#走者を一人増やす
runner+=1
if runner>=3
#走者が2人以上たまっていたらランナーを本塁に返す
runner=2
sumScore+=1
end
else
#凡打なのでアウトカウントを増やすだけ
outCount+=1
if outCount == 3
#3アウトチェンジしてループを抜ける
runner=0
outCount=0
break
end
end
#次のバッターに交代
batter+=1
#9番打者を打ち終わったら一番に戻る
batter = (batter-1)%9 + 1
}
if iningCount == 9
#9回が終了したらイニングと打順をリセットする
iningCount=0
batter=1
end
}
##最後に合計得点を出力
puts sumScore
結果
打線の組み方 | 上位打線に強打者 | 下位打線に強打者 | 交互に並べる |
---|---|---|---|
1試合平均得点 | 1.57 | 1.52 | 1.50 |
という結果になりました。ものすごく簡単な検証でしたが、強打者は分散して配置するよりも、下位打線でも良いから連続させて打順を組む方が効果的ということがわかります。
今回のルールでは連打が出ないと点が入らないので、チャンスでいかに打てるかが大事です。強打者が作ったチャンスを平凡な打者が潰してしまうのを減らすためには、強打者は集中させるのがいいという直感と合致しますね。
おまけ 得点が少なすぎるので調整
上のルールにおける検証結果では強打者を上位に並べても1試合あたり1,2点しか入らないということになり、あまりにも少なすぎるので、もう少し実際の野球に近づけてみました。
近年の野球において特に重視されるのは、出塁率と長打率です。野球は27個のアウトを取られるまでは永遠に攻撃を続けられるスゴロクゲームと捉えることができます。
スゴロクに置いて重要なのは
- いかにアウトにならず塁に出られるか
- 長打によって一度にたくさん駒を進められるか
の2点です。実際の野球ではヒットでなくても四球で塁に出ることができますし、本塁打が出ればその時点で得点が入ります。
プロ野球で打率3割を残せるのはごく一部ですが、出塁率3割はレギュラークラスなら超えておかなければならない数字です。
コードで本塁打と四球を反映させてみた
ここからは打線の組み方というよりも本物の野球の点の入り方に近づけることを目標とします。四球は単打と同じ扱いとし、全員の出塁率を一律に3割2分とします。3回に1回塁に出る計算になります。
また、出塁のうちの10本の1本はホームランが出て、ランナーを全員返すと仮定しましょう。(この辺りの仮定は実際のプロ野球のパリーグのデータを用いています)
#チーム全員の出塁率を宣言する
average=[0.32,0.32,0.32,0.32,0.32,0.32,0.32,0.32,0.32]
sumScore=0
batter=1
outCount=0
runner=0
iningCount=0
90000.times {
iningCount+=1
loop {
hit = rand(1..100)
hit = hit/100.0
if hit <= average[batter-1]
runner+=1
if rand(1..10) == 1
#10回に一回はホームランが出て全員が帰りランナーを0に戻す
sumScore+=runner
runner=0
elsif runner>=3
runner=2
sumScore+=1
end
else
outCount+=1
if outCount == 3
runner=0
outCount=0
break
end
end
batter+=1
batter = (batter-1)%9 + 1
}
if iningCount == 9
iningCount=0
batter=1
end
}
puts sumScore
四球とホームランを考慮した結果、1試合あたりの平均得点は4.4点となりました。DH制を利用しているパリーグの昨年の平均得点が4.31点だったので、大雑把なモデルの割にはかなり近い感じになりました。
まとめと展望
出塁率と長打率さえ調整すれば、実際の野球と近い平均得点を出せることがわかりました。ここからさらに実際の野球に近づけるには、以下のことをする必要があるでしょう。
- ホームランバッターを上位におく
- 3連続出塁で1点も入らない場合も想定する
- 打者の出塁率の差を考慮する
- 2塁打を考慮する(3塁打は少なすぎて誤差の範囲)
バント、盗塁はセイバーメトリクスでは推奨されていませんし、エラーも出塁と同値と考えて良いのかもしれません。コードが簡潔に保てる範囲内で色々試してみたいと思います。