球審は早く試合を終了させたい?フレーミング指標で検証する
球審がストライクとコールするか否かは捕手のキャッチング、打席の左右、カウントなどいろいろな要素が絡んでいる。今回はその中でイニングと点差の影響を検証する。
イニング別
始めにイニング別のフレーミング指標の比較を行う。(フレーミング指標は以前の投稿と同じものを使う。)
折れ線グラフは値が高いほどストライクとコールされやすく低いほどストライクとコールをされにくいことを表している。ストライクと最もコールされやすいのは9回だ。一方で延長戦に突入すると大きく値が低下する。このことから球審はストライクのコール率を調整して試合を早く終了させようとしているのではないかと推測される。
9回の点差別
最もストライクとコールされやすい9回のストライクコール率を点差別でみていくとほとんどの点差で平均と比較したストライクコール数(CSAA)は平均(0.00)を超えているが同点(0点)の時はコール率が大幅に低下している。試合を早く終了させるために点差がついてる場面ではアウトを稼ぎやすいようにストライクのコール率が上がるが同点時には点が入りやすいようにストライクのコール率が下がるのではないかと推測される。
延長戦の状況別
ストライクとコールされにくい延長戦について状況別で見ていく。同点時とビハインド時はストライクとコールされにくいのに対しリード時は飛躍的にコール率が上がる。同点時には早く点を取ってもらいたいがためにコール率が下がりビハインド時もその回で終了させるためにややコール率を下げて追加点を取りやすい環境にしリード時には試合を終了させるためにコール率を上げているのではないかと思われる。
審判は試合を早く終了させたい?
ストライクのコール率を状況別で見ていくと9回以降、基本的に球審は試合を早く終了させようとストライクコール率を調整しているようだ。
抑え投手が同点の場面はセーブ機会(3点差以内のリード)より抑えるのが難しいと言われるのはこうした球審のコール率の変化の影響があるのではないかと推測する。
実際2017-2020で9回時のセーブ機会と同点、両方の場面で50打席以上経験した投手の状況別平均wOBAを算出すると同点のほうが36ポイントもwOBAが高くなっている。
CSAAを比較してみると9回のセーブ機会では0.012だったCSAAが-0.017まで低下してしまう。これを2020年の1000投球以上の捕手で例えるとセーブ機会ではリーグ5位相当の捕手と組んだ時と同じアドバンテージを受けられる一方で同点時にはリーグワースト2位(74位)の捕手と組んだ時と同じディスアドバンテージを背負うことになることを意味する。影響はかなり大きい。
セーブシチュエーション(9回3点差以内のリード)はストライクとコールしてもらいやすいことを考えると試合終盤を任せる投手候補が2人いた場合、コントロールに難がある投手のほうに9回を任せたほうがコントロール難を補えチームトータルで失点を抑止できる可能性がある。
Rのコード
#dfには2017-2020MLBのデータが入っている
#フレーミング機会のみにデータを絞る
df <- df %>%
select(description,plate_x,plate_z,balls,strikes,stand,pitch_type,inning,home_score,away_score,inning_topbot)
df <- df %>% filter(description == "called_strike" | description == "ball")
Framing <- df %>% filter(description == "called_strike" | description == "ball")
#垂直方向の座標が0未満の投球は評価から除外
Framing <- Framing %>% filter(plate_z > 0)
#投球位置データをフィートからセンチメートルにする
#ボールカウントの列を作成
#ifelse関数でストライクを1,ボールを0とする列を作成
#守備側チームの点差状況を計算
Framing <- Framing %>%
mutate(plate_x_cm = plate_x * 30.48,
plate_z_cm = plate_z * 30.48,
count = paste(balls,"-",strikes),
called_strike = ifelse(description == "called_strike" ,1,0),
point = ifelse(inning_topbot == "Top",home_score - away_score,away_score - home_score),
status = case_when(
point < 0 ~ " < 0",
point == 0 ~ " == 0",
point > 0 ~ " > 0"),
save_situation = case_when(
point >= 1 & point <= 3 & inning == 9 ~ "セーブ機会",
point == 0 & inning == 9 ~ "同点",
TRUE ~ "それ以外"))
#cut関数で投球コースを縦横5cmずつに刻む
Group <- seq(-60,60,5)
Group_2<- seq(0, 120 , 5)
Framing$plate_x_bin <- with(Framing, cut(plate_x_cm, Group))
Framing$plate_z_bin <- with(Framing, cut(plate_z_cm, Group_2))
#投球コース、カウント、左右打席ごとのストライク期待値を出す
expected_called_strike <- Framing %>%
group_by(plate_x_bin,plate_z_bin,count,stand,pitch_type)%>%
dplyr::summarise(N = n(),
sumCS = sum(called_strike, na.rm = TRUE),
xCS = sumCS / N )
#NAになってる行を削除
expected_called_strike <- subset(expected_called_strike, !(is.na(expected_called_strike$plate_x_bin)))
expected_called_strike <- subset(expected_called_strike, !(is.na(expected_called_strike$plate_z_bin)))
#left_joinで各組合せのストライク期待値を結合
Framing <- Framing %>%
left_join(expected_called_strike %>%
select(plate_x_bin,plate_z_bin,count,stand,pitch_type,xCS))
#ストライク-ストライク期待値の列を作成
Framing <- Framing %>% mutate(CS_AA = called_strike - xCS)
#フレーミング機会1000以上のイニングごとにそれぞれのフレーミング指標を作成
Framing_inning <- Framing %>%
group_by(inning) %>%
dplyr::summarise(N = n(),
CSAA_per_pitch = mean(CS_AA, na.rm = TRUE))%>%
filter(N >= 1000)
ggplot(Framing_inning ,aes(x=inning,y=CSAA_per_pitch))+
geom_line()+
geom_point(size = 4,shape=21,fill="white")+
ggtitle("MLB2017-2020 イニング別 CSAA_per_pitch min1000FrmCH") +
scale_x_continuous(breaks = seq(1,13,1) , limits = c(1,13))+
geom_hline(yintercept = 0)
#9回のフレーミング機会1000以上の点差ごとのフレーミング指標を作成
Framing_9inning <- Framing %>%
filter(inning == 9) %>%
group_by(point) %>%
dplyr::summarise(N = n(),
CSAA_per_pitch = mean(CS_AA, na.rm = TRUE)) %>%
filter(N >= 1000)
ggplot(Framing_9inning ,aes(x=point,y=CSAA_per_pitch))+
geom_line()+
geom_point(size = 4,shape=21,fill="white")+
ggtitle("MLB2017-2020 9回の点差別 CSAA_per_pitch min1000FrmCH") +
scale_x_continuous(breaks = seq(-8,10,1) , limits = c(-8,10))+
geom_hline(yintercept = 0)
#延長戦状況別のフレーミング指標を作成
Framing_extra <- Framing %>%
filter(inning >= 10 ) %>%
group_by(status) %>%
dplyr::summarise(N = n(),
CSAA_per_pitch = mean(CS_AA, na.rm = TRUE))
ggplot(Framing_extra ,aes(x=status,y=CSAA_per_pitch))+
stat_summary(geom = "line", group = 1 ) +
ggtitle("MLB2017-2020 延長戦 状況別 CSAA per Pitch")+
geom_hline(yintercept = 0)
#9回状況別のwOBA
df <- df %>%
mutate(point = ifelse(inning_topbot == "Top",home_score - away_score,away_score - home_score),
status = case_when(
point < 0 ~ " < 0",
point == 0 ~ " == 0",
point > 0 ~ " > 0"),
save_situation = case_when(
point >= 1 & point <= 3 & inning == 9 ~ "セーブ機会",
point == 0 & inning == 9 ~ "同点",
TRUE ~ "それ以外"))
wOBA_9inning <- df %>%
filter(inning == 9)%>%
group_by(pitcher_name,save_situation) %>%
dplyr::summarise(wOBA_value = sum(woba_value,na.rm = TRUE),
wOBA_denom = sum(woba_denom,na.rm = TRUE),
wOBA = wOBA_value / wOBA_denom)%>%
filter(wOBA_denom >=50)
#それ以外を削除
wOBA_9inning <- wOBA_9inning %>%
filter(save_situation != "それ以外")
#leadとfilterでセーブ機会と同点の両方の場面で50以上投げた投手以外を除外
wOBA_9inning <- wOBA_9inning %>%
mutate(lead_pitcher_name = lead(pitcher_name),
lead_wOBA_value= lead(wOBA_value),
lead_wOBA_denom = lead(wOBA_denom))
wOBA_9inning <- wOBA_9inning %>%
filter(pitcher_name == lead_pitcher_name)
wOBA_9inning_Dif <- wOBA_9inning %>%
group_by(save_situation)%>%
dplyr::summarise(セーブ機会wOBA = sum(wOBA_value)/sum(wOBA_denom),
同点wOBA = sum(lead_wOBA_value)/sum(lead_wOBA_denom))
wOBA_9inning_Dif <- wOBA_9inning_Dif[, colnames(wOBA_9inning_Dif) != "save_situation"]
wOBA_9inning_Dif[,1:2] <- round(wOBA_9inning_Dif[,1:2],3)
wOBA_9inning_Dif %>% gt()%>%
tab_header(
title="両方の場面で50打席以上経験した投手の平均wOBA")
#9回状況別のフレーミング指標を作成
Framing_save <- Framing %>%
filter(inning == 9 ) %>%
group_by(save_situation) %>%
dplyr::summarise(N = n(),
CSAA_per_pitch = mean(CS_AA, na.rm = TRUE))
#それ以外を削除
Framing_save <- Framing_save %>%
filter(save_situation != "それ以外")
ggplot(Framing_save ,aes(x=save_situation,y=CSAA_per_pitch))+
stat_summary(geom = "line", group = 1 ) +
ggtitle("MLB2017-2020 9回 状況別 CSAA per Pitch")+
geom_hline(yintercept = 0)
この記事が気に入ったらサポートをしてみませんか?