得点分布の多峰性

MikuHatsune2010-11-09

野球で得点分布の山がどうなるのかをちょっと考えよう。
俺の嫁にどれだけ歌わせても嫌と言わないように、コンピュータもどれだけ計算させても嫌と言わないので、とりあえず、シミュレーションするに当たってこちら側で振っているパラメータをいじくってみました。
前回までのプログラムをちょっと改変。

one.game.score<-
        function(batter,out.count){                   # 変数としてチェンジまでのアウトカウントもいじくれる
          si  <- c(1);dou <- c(1,0);tri <- c(1,0,0);hr  <- c(1,0,0,0)
          out.count<- out.count
          total.score<- rep(0,9)
          batter.box<- 1
          for(t in 1:9){
            runner<- rep(0,9)
            out<- 0
            repeat{
              x<- sample(c(1,2,3,4,5),prob=batter[batter.box,],size=1)
              switch(x,
                     (out<- out + 1),
                     (runner<- append(runner,si)),
                     (runner<- append(runner,dou)),
                     (runner<- append(runner,tri)),
                     (runner<- append(runner,hr))
              )
              switch(batter.box,
                     (batter.box<- 2),(batter.box<- 3),(batter.box<- 4),
                     (batter.box<- 5),(batter.box<- 6),(batter.box<- 7),
                     (batter.box<- 8),(batter.box<- 9),(batter.box<- 1)
              )
              if(out>(out.count - 1)){
                break
              }
            }
            total.score[t]<- sum(runner[c(1:(length(runner)-3))])
          }
          return(sum(total.score))
        }

hist.data<-
function(n,batter,out.count){                               # n試合
  data1<- rep(0,n)                                          # batterは5行9列の打撃確率行列
  for(i in 1:n){
    data1[i]<- one.game.score(batter,out.count)
  }
  result.count<- rep(0,(max(data1) + 1))
  for(p in 0:max(data1)){
    result.count[p]<- length(which(data1 == p))
  }
  #print(result.count/n)                            # n試合したときの各得点の割合が返る 
  #return(histogram(data1))                         
  #return(result.count/n)                           
  return(data1)                                     # 得点の生データを返す
}

以下、10000試合してみたいと思う。
 
アウトカウントを変える。1イニング1アウトでチェンジから、8アウトでチェンジまで増やしてみた。
batterは9人とも同じ打撃確率。

batter<- matrix(c(0.71,0.20,0.06,0.01,0.02),9,5,byrow=T)
title.name<- c("out.count 1","out.count 2","out.count 3","out.count 4","out.count 5","out.count 6","out.count 7","out.count 8")
xlab<- "Score"
trials<- 10000
par(mfrow=c(2,4))
for(i in 1:8){
  hist(hist.data(trials,batter,i),main=title.name[i],xlab=xlab,col="pink")
}


峰はひとつしかないようで、裾も右にだら〜と広がるのではなく、流行値がずれて行ってるみたい。
 
アウト打撃確率を変える。単純化して、アウトかシングルヒットしか打たないとして、シングルヒットの確率を0.1から0.8まで変えた。チェンジになるアウトカウントは3つ。

title.name<- c("Hit probability 0.1","Hit probability 0.2","Hit probability 0.3","Hit probability 0.4",
               "Hit probability 0.5","Hit probability 0.6","Hit probability 0.7","Hit probability 0.8"
       )
par(mfrow=c(2,4))
for(x in 1:8){
  p<- 0.1*x
  one.batter<- c(1-p,p,0,0,0)
  team<- c()
    for(y in 1:9){
      team<- rbind(team,one.batter)
    }
  xlab<- "Score"
  trials<- 10000
  hist(hist.data(trials,team,3),main=title.name[x],xlab=xlab,col="pink")
  }


これも峰は分離してこないようだ。ヒット確率0.1でもがんばってちょっと点取ってる。すげえ。
 
各ヒットの確率を変える。先生がつぶやいておられたように、ヒットのパターンが4つあるので、もしかしたら4峰性か!?
シングル、ツーベース、スリーベース、HRが等確率だけど0.05から0.20まで上がる。
チェンジアウトカウントは3つ。

title.name<- c("Hit probability each 0.05","Hit probability each 0.10","Hit probability each 0.15","Hit probability each 0.20")
par(mfrow=c(1,4))
for(x in 1:4){
  p<- 0.05*x
  one.batter<- c(1-4*p,p,p,p,p)
  team<- c()
    for(y in 1:9){
      team<- rbind(team,one.batter)
    }
  xlab<- "Score"
  trials<- 10000
  hist(hist.data(trials,team,3),main=title.name[x],xlab=xlab,col="pink")
  }


う〜ん(・ω・)
急に思い出したけど、rdirichlet使っても峰は増えなかった。
 
そういえば3次元世界の結果はどうなっているのか気になった。

# 2010年ペナントレース阪神の各試合の得点結果
# ちまちま打つの疲れたZE☆
hanshin<- c(7,4,2,6,6,5,2,1,5,0,5,3,5,7,9,3,2,3,8,5,1,7,3,5,9,5,4,9,8,0,2,9,10,
            8,4,2,4,3,3,4,3,6,3,5,8,1,1,4,3,2,7,6,4,9,3,1,8,4,8,7,6,13,9,9,2,4,1,11,
            5,10,8,2,6,3,6,6,3,7,6,1,9,11,2,5,4,5,6,3,5,8,2,8,1,1,1,0,6,10,6,4,9,12,
            11,10,5,3,0,4,22,1,0,9,12,13,10,6,4,3,11,1,1,2,4,2,5,3,5,2,1,4,4,0,0,6,
            8,5,3,3,0,11,7,17,5,0)
# 2010年で試合出場が多いっぽい選手を勝手に選出。
Tigars<- rbind(c(0.6508972,0.2593801,0.05709625,0.004893964,0.027732463),
               c(0.6504065,0.2926829,0.04471545,0.010162602,0.002032520),
               c(0.6991304,0.2034783,0.05391304,0.010434783,0.033043478),
               c(0.6894737,0.2035088,0.07368421,0.000000000,0.033333333),
               c(0.7039007,0.1861702,0.02659574,0.000000000,0.083333333),
               c(0.7592068,0.1614731,0.03399433,0.000000000,0.045325779),
               c(0.6967509,0.1985560,0.05234657,0.000000000,0.052346570),
               c(0.7453416,0.1614907,0.07453416,0.000000000,0.018633540),
               c(0.9000000,0.1000000,0.00000000,0.000000000,0.000000000)
               ) 
# 確認
apply(Tigars,1,sum)
# シミュレーション用仮想阪神を作る。打率はみんな平均値。
Tigars.simulation<- matrix(apply(Tigars,2,mean),9,5,byrow=T)
# これで144試合ペナントしたときの得点分布を作成。
titles<- c("Real","Tigars.simulation","Uniform probability")    
par(mfcol=c(1,3))
hist(hanshin,col="pink",main=titles[1],freq=F,xlim=c(0,max(hanshin)),xlab="Score")
hist(hist.data(144,Tigars,3),col="pink",main=titles[2],freq=F,xlim=c(0,max(hanshin)),xlab="Score")
hist(hist.data(144,Tigars.simulation,3),col="pink",main=titles[3],freq=F,xlim=c(0,max(hanshin)),xlab="Score") 


左から、現実の阪神、現実の阪神の打撃確率を用いたシミュレーション、9人平均化してみんな同じ確率のシミュレーション。
144試合しかしていないから描くたびにふらつくけど、シミュレーションが現実より点を取っているふうには見えない。
なんかここらへんが戦術なのかなあ…
思ったのが、現実では完封されている試合が意外と少ない。
得点分布が山というよりむしろ坂。
 
この方法では、打席に立ったひとりひとりの打者に結果を与えているので、数学的になんか考えようと思ったら難しいのか…?
こちらのふたつめ、推移行列みたいなのを用意するとどうにか考えられそう(やるのはNKうそ自分でも考えるよ!)。
終わり。
 
朝、大学病院に行ったら、なんとかけいおんフェアのグッズをゲットすることができた。
巷ではすんごい人気だ。秋葉原も戦場だったらしい。
朝では安いお菓子が少なかったし、澪と梓と集合版で手を打ったが、講義終了後に揃えたくて再び行ったら
 
ない…だ…と…?
 
オレ「けいおんファイルの台座ください」
店員「?。少々お待ち下さい…」

店員「店長からの許可が下りましたのでどうぞお持ちください」
 
大学病院のロビーを歩くオレさすがにちょっと恥ずかしかったwww