MLBの周回効果を定量化する

投手が何度も同じ打者と対戦すると打者が慣れて打ちやすくなるとは以前から言われていることだが現在、その効果は定量化され認知されMLBでは3巡目になると投手を変えるという戦術をとるチームも存在する。(2020年のワールドシリーズで好投していたスネルを3巡目になるからと交代したことは記憶に新しい)今回は2017-2020年のMLBで周回効果がどの程度投手成績に影響を与えるか定量化する。

検証方法

同じ試合で同じ打者と3回以上対戦する登板があった投手を対象にそれぞれの巡目での各種成績の平均をとる。

結果

周回効果

結果は以上のようになった。まずwOBA(打席当たりの得点創出、投手にとっては失点のリスク)を見てみると対戦を重ねるごとに上昇していくことがわかる。特に2巡目→3巡目の上がり幅は21ポイントと大きく1巡目と比べると28ポイントも上がっており1巡目と3巡目では全く質の異なる投手に代わってしまっている。レイズのキャッシュ監督がスネルを交代させた理由も理解できる数字ではないだろうか。

内訳を見てみるとK%は対戦を重ねるごとに徐々に下がっていく。2巡目、3巡目とも自力アウトを取ることが難しくなるのが失点リスク増の要因の1つだろう。BB%は横這いであり失点リスクの増大の要因は四球にはなさそうだ。HR%とwOBAcon(打球のwOBA)は2巡目まではあまり変わらないものの3巡目以降で跳ね上がる。3巡目で失点リスクが跳ね上がるのは打球による影響が大きそうだ。

また対戦を重ねると打たれやすくなるのはスタミナが落ちて球威が落ちるのが原因とも考えたがフォーシームの球速と縦変化量を見てみると大きな変化はなく原因は別にあると思われる。

Plate Discipline

(2021/5/1 追記)

周回効果 Plate

周回ごとのPlate Disciplineを見ていくと周回するごとに打者のSwing%が上昇していることがわかる。対戦を重ねると打者は積極的にスイングを試みる傾向にあるようでK%、BB%の低下の要因の1つと言えそうだ。

Batted Ball

(2021/5/4追記)

周回効果 打球

Batted Ballは以上のようになった。wOBAconは3巡目以降に大きく上がっている。Barrel/BBEの上昇の影響が大きそうだがそれ以外の要素に大きな変化はなかった。

library(tidyverse)

#dfには2017-2020年のstatcastのデータが入っている

df <- df %>% 
 select(game_pk,at_bat_number,pitch_number,events,balls,strikes,description,type,
        pitcher,batter,game_year,woba_denom,woba_value,pitch_type,release_speed,
        pfx_z)
        
#試合順、打席順、投球順に並べ替える
df <- df %>%
 arrange(game_pk,at_bat_number,pitch_number)
 
#投球結果の列を作る、打席idを設定
strikeouts <- c("strikeout", "strikeout_double_play")
df <- df %>%
 mutate(K_FL = ifelse(events %in% strikeouts, 1, 0),
        BB_FL = ifelse(events == "walk",1,0),
        HR_FL = ifelse(events == "home_run",1,0),
        id = paste(game_pk,pitcher,batter,at_bat_number),
        id_vs = paste(game_pk,pitcher,batter))
        
 #id一覧を作る
Order_penalty = df %>%
 select(game_pk,pitcher,batter,at_bat_number,id,id_vs)
        
 #重複idを削除
Order_penalty <- Order_penalty %>% distinct(id,.keep_all=TRUE) 

#〇巡目抽出用の列を作る
Order_penalty <- Order_penalty %>%
 arrange(game_pk,pitcher,batter)%>%
 mutate(
   lag_id_vs = lag(id_vs),
   lag_id_vs_2 = lag(lag_id_vs),
   effect_2 = ifelse(id_vs == lag_id_vs ,2,1),
   lag_effect = lag(effect_2),
   effect_3 = ifelse(effect_2 == 2 & lag_effect == 2,3,1),
   id_effect_2 =paste(game_pk,pitcher,batter,effect_2))
   
#3巡以降対戦した組み合わせをまとめる

id_order_vs_ALL <- Order_penalty %>%
 group_by(id_vs)%>%
 filter(effect_3 == 3)%>%
 select(id_vs)
 
#1巡目
id_order_vs_1 <- Order_penalty %>%
 distinct(id_vs,.keep_all=TRUE)
id_order_vs_1 <- id_order_vs_1 %>%
 mutate(effect_in1 = 1)%>%
 select(id,id_vs,effect_in1)
 
id_order_vs_1 <- inner_join(id_order_vs_ALL,id_order_vs_1)

df <- left_join(df,id_order_vs_1)

#2巡目
id_order_vs_2 <- Order_penalty %>%
 filter(id_vs == lag_id_vs)%>%
 filter(lag_id_vs != lag_id_vs_2)
 
id_order_vs_2 <- inner_join(id_order_vs_ALL,id_order_vs_2)

id_order_vs_2 <- id_order_vs_2 %>%
 mutate(effect_in2 = 1)%>%
 select(id,id_vs,effect_in2)
 
df <- left_join(df,id_order_vs_2)

#3巡目
id_order_vs_3 <- Order_penalty %>%
 filter(id_vs == lag_id_vs)%>%
 filter(lag_id_vs == lag_id_vs_2)
 
id_order_vs_3 <- inner_join(id_order_vs_ALL,id_order_vs_3)

id_order_vs_3 <- id_order_vs_3 %>%
 mutate(effect_in3 = 1)%>%
 select(id,id_vs,effect_in3)
 
df <- left_join(df,id_order_vs_3)

Through_1 <- df %>%
 filter(effect_in1 == 1) %>%
 dplyr::summarise(PA_1 = sum(woba_denom,na.rm=TRUE),
                  Kpct_1 = round(sum(K_FL,na.rm=TRUE)/PA_1*100,1),
                  BBpct_1 = round(sum(BB_FL,na.rm=TRUE)/PA_1*100,1),
                  HRpct_1 = round(sum(HR_FL,na.rm=TRUE)/PA_1*100,1),
                  wOBA_1 = round(sum(woba_value,na.rm=TRUE)/PA_1,3))
                  
Through_1_con <- df %>%
 filter(effect_in1 == 1) %>%
 filter(type == "X")%>%
 dplyr::summarise(PA_1 = sum(woba_denom,na.rm=TRUE),
                  wOBAcon_1 = round(sum(woba_value,na.rm=TRUE)/PA_1,3))
                  
Through_1_FF <- df %>%
 filter(effect_in1 == 1) %>%
 filter(pitch_type == "FF") %>%
 dplyr::summarise(mean_velo = mean(release_speed,na.rm = TRUE)*1.609,
                  mean_pfx_z = mean(pfx_z,na.rm=TRUE)*30.48)
                  
Through_2 <- df %>%
 filter(effect_in2 == 1) %>%
 dplyr::summarise(PA_2 = sum(woba_denom,na.rm=TRUE),
                  Kpct_2 = round(sum(K_FL,na.rm=TRUE)/PA_2*100,1),
                  BBpct_2 = round(sum(BB_FL,na.rm=TRUE)/PA_2*100,1),
                  HRpct_2 = round(sum(HR_FL,na.rm=TRUE)/PA_2*100,1),
                  wOBA_2 = round(sum(woba_value,na.rm=TRUE)/PA_2,3))
                  
Through_2_con <- df %>%
 filter(effect_in2 == 1) %>%
 filter(type == "X")%>%
 dplyr::summarise(PA_2 = sum(woba_denom,na.rm=TRUE),
                  wOBAcon_2 = round(sum(woba_value,na.rm=TRUE)/PA_2,3))
                  
Through_2_FF <- df %>%
 filter(effect_in2 == 1) %>%
 filter(pitch_type == "FF") %>%
 dplyr::summarise(mean_velo = mean(release_speed,na.rm = TRUE)*1.609,
                  mean_pfx_z = mean(pfx_z,na.rm=TRUE)*30.48)
                  
Through_3 <- df %>%
 filter(effect_in3 == 1) %>%
 dplyr::summarise(PA = sum(woba_denom,na.rm=TRUE),
                  Kpct = round(sum(K_FL,na.rm=TRUE)/PA*100,1),
                  BBpct = round(sum(BB_FL,na.rm=TRUE)/PA*100,1),
                  HRpct = round(sum(HR_FL,na.rm=TRUE)/PA*100,1),
                  wOBA = round(sum(woba_value,na.rm=TRUE)/PA,3))
                  
Through_3_con <- df %>%
 filter(effect_in3 == 1) %>%
 filter(type == "X")%>%
 dplyr::summarise(PA = sum(woba_denom,na.rm=TRUE),
                  wOBAcon_3 = round(sum(woba_value,na.rm=TRUE)/PA,3))
                  
Through_3_FF <- df %>%
 filter(effect_in3 == 1) %>%
 filter(pitch_type == "FF") %>%
 dplyr::summarise(mean_velo = mean(release_speed,na.rm = TRUE)*1.609,
                  mean_pfx_z = mean(pfx_z,na.rm=TRUE)*30.48)

この記事が気に入ったらサポートをしてみませんか?