打順最適化でどのチームが勝ちやすいかシミュレーション

MikuHatsune2011-01-30

こちらで打順をいじくって、1試合の得点分布がどうなるかを調べた。
結果、パワーヒッターの打順が(1,9)、(2,5,8)、(3,7)、(4,6)では同一の結果になることがわかった。
(1,9)はおそらく、1番打者が第1イニングで打席に立った後は9番打者の後ろに並ぶことになるから、初回で必ず取る1点はたいして影響しない、ということだと思う。
パワーヒッターは必ずHRを打つ設定なので、パワーヒッターの前に何人走者がいるか、1試合中にパワーヒッターに何回打順が回ってくるか、が重要なのかもしれない。
ということで解析項目として
・パワーヒッターの打順の前にたまっている走者数(の期待値)
・1試合中にパワーヒッターが打席に立つ回数(の期待値)
とか考えられそう。
 
で、打順を組み換えた9チームでペナントレースをしてみた。
1チームあたり1000回試合を総当たり戦で行う。つまり8000試合。
勝率は、勝数を勝数と負数の和で割ったものとする。
(勝率が十分安定したところをみて1000試合に設定した。)

結果

Data<- matrix(c(0.4713638,0.5465132,0.5895748,
                0.5813953,0.5371304,0.4648214,
                0.4788732,0.4525079,0.3777322),nr=1)

上で分類したチーム同士についても地味にやってみた。

game<- 1000
battle.cmb<- combinations(people,2)
wdldata<- matrix(0,nr=nrow(battle.cmb),nc=3)
dimnames(wdldata)<- list(1:nrow(wdldata),c("win","draw","lose"))
for(g in 1:game){
  for(b in 1:nrow(battle.cmb)){
    D1<- one.game.score(team.array[,,battle.cmb[b,1]],Nout,Nbase,people,Ninning)
    D2<- one.game.score(team.array[,,battle.cmb[b,2]],Nout,Nbase,people,Ninning)
    wdldata[b,]<- wdldata[b,]+c(sum(D1>D2),sum(D1==D2),sum(D1<D2))
  }
}
cbind(battle.cmb,apply(wdldata,1,winprob))

2番対5番以外については、パワーヒッターの打順が早いほうがよく勝つようだ。
2番対5番については、5番打者の前にうまく走者がたまる…のかな?
まあ、もうちょっと考えてみよう。

# パラメータ
library(MCMCpack)
library(gtools)
library(expm)
game<- 1000
Nbase<- 4
Nout<- 3
Ninning<- 9
people<- 9
Tigars<- rbind(c(0,0,0,0,1),
               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.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)
               ) 
b1<- mapply(rep,2:people,1:(people-1))
b2<- mapply(rep,2:people,(people-1):1)
b<-  diag(1,people)
b[upper.tri(b)]<- unlist(b1)
b[lower.tri(b)]<- unlist(b2)
Tigars.array<- array(0,c(people,Nbase+1,2))
team.array<- array(0,c(people,Nbase+1,people))
for(t in 1:people){
  team.array[,,t]<- Tigars[b[t,],]
}
# 必要な関数
winprob<- function(vec){
  a<- vec["win"]/(vec["win"]+vec["lose"])
  return(a)
}
one.game.score<-
        function(batter,out.count,base,people,Inning){
          hitpattern<- c(1,lapply(mapply(rep,0,1:(base-1)),append,c(1),after=F))
          out.count<- out.count
          total.score<- rep(0,Inning)
          batter.box<- 1
          for(t in 1:Inning){
            runner<- rep(0,people)
            out<- 0
            repeat{
              x<- sample(1:(base+1),prob=batter[batter.box,],size=1)
              if(x==1){
                out<- out+1
                }else{
                  runner<- append(runner,hitpattern[[x-1]])
                }
              batter.box<- batter.box+1
              if(batter.box>9){
                batter.box<- 1
              }
              if(out>(out.count - 1)){
                break
              }
            }
            total.score[t]<- sum(runner[c(1:(length(runner)-(base-1)))])
          }
          return(sum(total.score))
        }
hist.data<- function(n,batter,out.count){ 
  data1<- rep(0,n)
  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))
  }
  return(data1)     
}
# ここからスタート。
game<- 1000
battle.cmb<- combinations(people,2)
wdldata<- matrix(0,nr=nrow(battle.cmb),nc=3)
dimnames(wdldata)<- list(1:nrow(wdldata),c("win","draw","lose"))
battledata<- matrix(0,nr=people,nc=3)
dimnames(battledata)<- list(1:people,c("win","draw","lose"))
winprobdata<- matrix(0,nr=people,nc=game)
dimnames(winprobdata)<- list(1:people,1:game)
names(dimnames(winprobdata))<- c("team.No","Game cycles")
for(g in 1:game){
  for(b in 1:nrow(battle.cmb)){
    D1<- one.game.score(team.array[,,battle.cmb[b,1]],Nout,Nbase,people,Ninning)
    D2<- one.game.score(team.array[,,battle.cmb[b,2]],Nout,Nbase,people,Ninning)
    wdldata[b,]<- c(sum(D1>D2),sum(D1==D2),sum(D1<D2))
  }
  res<- cbind(battle.cmb,wdldata)
  b.data<- matrix(0,nr=people,nc=3)
  dimnames(b.data)<- list(1:people,c("win","draw","lose"))
  for(nr in 3:5){
    for(t in 1:people){
      b.data[t,nr-2]<- sum(res[which(res[,1]==t),nr])
    }
  }
  for(nr in 5:3){
    for(t in 1:people){
      b.data[t,6-nr]<- b.data[t,6-nr]+sum(res[which(res[,2]==t),nr])
    }
  }
  battledata<- battledata+b.data
  winprobdata[,g]<- apply(battledata,1,winprob)
}
Layout<- matrix(c(1,1,1,1,2,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1),5,5,byrow=T)
layout(Layout)
persp(winprobdata,col=rainbow(game*people),phi=30,theta=140,zlim=c(0,1),
      xlab="Team.No",ylab="Game cycles",zlab="win probability",
      main="Win probability")
image(winprobdata, xlab="Team.No",ylab="Game cycles")