一塁走者のSprint Speed(走力)は打撃成績に影響を与えるのか。
一塁走者に俊足の走者がいるとバッテリーにプレッシャーがかかると言われることがある。主張としては俊足の走者が一塁上にいるとバッテリーは盗塁や長打で本塁に還られることを警戒するというものだが実際に一塁走者の走力は打者の打撃成績に影響を与えるのか。
走力を測る指標、Sprint Speed
MLBAMが運営するBaseball SavantではSprint Speedと呼ばれる1秒に何フィート移動したかを表す走力を測る指標が公開されている。MLB平均は約27ft/sとされている。このSprint Speedを用い一塁走者が打者の打撃成績に影響をどれだけ与えるかを定量化する。
検証
まず走力の基準を定義する。Sprint Speedが26ft/s未満の選手をSLOW、26ft/s以上28ft/s以下の選手をAVERAGE、28ft/sより上の選手をFASTと定義する。
各タイプの走者が塁上にいるときの打撃成績を算出することでその影響を測ろうとするやり方もあるがその方法を用いると塁上に俊足の走者がいることが多い状況では強打者が打席に立つ機会が多い等のバイアスを受ける可能性がある。そこで補正を行う。
補正の方法としては一塁走者が塁上にいて二塁塁上に走者がいない状態を除いた状況での各打者の打撃成績を算出する。対象とするのは2015-2020のMLBで同条件を満たした状態で300打席以上立った打者だ。このとき算出された打撃成績をその打者の期待値とする。そして対象打者が打席に立ち一塁に走者がいて二塁塁上に走者がいない状態での打撃成績と期待値の平均を算出する。
期待値の平均の計算については例えばwOBAの期待値が.360の選手が2回、.320の選手が1回打席に立った場合は
(.360+.360+.320)/(1+1+1)
と計算を行い期待値を算出する。
打撃成績の実測値と期待値を比較し一塁走者の走力が打撃成績に与える影響を定量化する。
検証結果
PA
PA(打席数)は以上のようになった。それなりのサンプルを得られたようだ。
wOBA
まずはwOBAを見ていく。wOBAとは打席で発生した各イベントに対し得点価値による重みを与えた打撃指標だ。大雑把に言えばOPSよりも得点の影響を測るのに優れた打撃指標という理解でよい。
wOBAの比較を行うとどのタイプもwOBAの期待値は上昇している。これは二塁が空いた状態で一塁に走者がいる状況では一塁手がベースにつきヒットゾーンが広まるため打撃成績が上昇しやすいのが一因と思われる。続いて各タイプの上がり幅を見てみるとAVERAGE、FASTでは上がり幅はほぼ同じでFASTの走者が特別打撃成績を上昇させる効果は確認できなかった。SLOWはやや上がり幅が小さいがそれでもwOBAの差にして5ポイント程度だ。wOBAで5ポイントというのは500打席で2.2点程度の得点創出の差である。
xwOBA
xwOBAは打球に対しては打球の速度と角度から推定した係数を非打球結果に対しては実際の打席結果に基づいた係数を使って計算したwOBAだ。打球結果に対しては打球の価値から計算を行うためシフトの影響を排除することが可能なのが特徴の1つだ。
xwOBAはどのグループも推定値と実測値に差が出ていない。どのグループも上昇していたwOBAとは対照的だがこれにより一塁走者が塁にいる状態だと打撃成績が上昇するのは守備のシフト(一塁手がベースにつく等)に起因するものだと推定できる。
まとめ
俊足(FAST)の一塁走者が打撃成績に与える影響は他のタイプと比べても特別大きなものではなく一塁走者が打撃成績に与える影響は確認できなかった。実感としてバッテリーにプレッシャーがかかるという話と実際に打撃成績にその影響が表れるのは別の話であり相手バッテリーにプレッシャーをかけるために一塁走者に俊足の選手を置くことは平均的にはあまり効果がないと言えそうだ。
library(tidyverse)
library(gt)
#dfには2015-2020のstatcastデータが入っている。
#必要な列に絞る
df <- df %>%
select(batter,on_1b,on_2b,on_3b,type,events,woba_value,woba_denom,
estimated_woba_using_speedangle,game_year,game_pk,
at_bat_number,pitch_number,type,barrel)
#Baseball Savantから入手した各年度のSprint Speedのデータをdfに紐づける
Sprint_speed_2015 <- read_csv("sprint_speed_2015.csv")
Sprint_speed_2015 <- Sprint_speed_2015 %>%
mutate(game_year = 2015)%>%
rename (on_1b = player_id)%>%
rename(sprint_speed_1b = sprint_speed) %>%
select(on_1b,sprint_speed_1b)
df <- left_join(df,Sprint_speed_2015)
Sprint_speed_2016 <- read_csv("sprint_speed_2016.csv")
Sprint_speed_2016 <- Sprint_speed_2016 %>%
mutate(game_year = 2016)%>%
rename (on_1b = player_id)%>%
rename(sprint_speed_1b = sprint_speed) %>%
select(on_1b,sprint_speed_1b)
df <- left_join(df,Sprint_speed_2016)
Sprint_speed_2017 <- read_csv("sprint_speed_2017.csv")
Sprint_speed_2017 <- Sprint_speed_2017 %>%
mutate(game_year = 2017)%>%
rename (on_1b = player_id)%>%
rename(sprint_speed_1b = sprint_speed) %>%
select(on_1b,sprint_speed_1b)
df <- left_join(df,Sprint_speed_2017)
Sprint_speed_2018 <- read_csv("sprint_speed_2018.csv")
Sprint_speed_2018 <- Sprint_speed_2018 %>%
mutate(game_year = 2018)%>%
rename (on_1b = player_id)%>%
rename(sprint_speed_1b = sprint_speed) %>%
select(on_1b,sprint_speed_1b)
df <- left_join(df,Sprint_speed_2019)
Sprint_speed_2019 <- read_csv("sprint_speed_2019.csv")
Sprint_speed_2019 <- Sprint_speed_2019 %>%
mutate(game_year = 2019)%>%
rename (on_1b = player_id)%>%
rename(sprint_speed_1b = sprint_speed) %>%
select(on_1b,sprint_speed_1b)
df <- left_join(df,Sprint_speed_2019)
Sprint_speed_2020 <- read_csv("sprint_speed_2020.csv")
Sprint_speed_2020 <- Sprint_speed_2020 %>%
mutate(game_year = 2020)%>%
rename (on_1b = player_id)%>%
rename(sprint_speed_1b = sprint_speed) %>%
select(on_1b,sprint_speed_1b)
df <- left_join(df,Sprint_speed_2020)
#必要なフラッグを作る
strikeouts <- c("strikeout", "strikeout_double_play")
df <- df %>%
mutate(
xwoba_value = ifelse(type =="X",estimated_woba_using_speedangle,woba_value),
Runner_1b = case_when(
sprint_speed_1b > 28 & is.na(.$on_2b) == TRUE ~"FAST",
sprint_speed_1b >= 26 & sprint_speed_1b <= 28 & is.na(.$on_2b) == TRUE ~ "AVERAGE",
sprint_speed_1b < 26 & is.na(.$on_2b) == TRUE ~"SLOW",
TRUE ~ "Standard"),
K_FL = ifelse(events %in% strikeouts, 1, 0),
BB_FL = ifelse(events == "walk",1,0))
#300PA以上の非盗塁機会以外の打者の打撃成績を算出
exp_batstats <- df %>%
filter(Runner_1b == "Standard")%>%
group_by(batter) %>%
dplyr::summarise(wOBA_value = sum(woba_value, na.rm = TRUE),
xwOBA_value = sum(xwoba_value ,na.rm=TRUE),
PA = sum(woba_denom, na.rm = TRUE),
bat_wOBA = wOBA_value / PA,
bat_xwOBA = xwOBA_value / PA,
K = sum(K_FL ,na.rm = TRUE),
BB = sum(BB_FL ,na.rm = TRUE),
barrel_CT = sum(barrel ,na.rm = TRUE),
bat_Kpct = K/PA*100,
bat_BBpct = BB/PA *100,
bat_barrelpct = barrel_CT / PA *100) %>%
filter(PA >= 300)
#対象選手を紐づけ
selected_players <- exp_batstats$batter
situations_of_interest <- c("FAST","AVERAGE","SLOW")
data <- df %>% filter(batter %in% selected_players)%>%
left_join(exp_batstats)%>%
filter(Runner_1b %in% situations_of_interest)
#推定値と実測値の打撃成績を算出
Runner_bat <- data %>%
group_by(Runner_1b)%>%
filter(woba_denom == 1)%>%
dplyr::summarise(ex_wOBA = round(mean(bat_wOBA, na.rm = TRUE),3),
ex_xwOBA = round(mean(bat_xwOBA, na.rm = TRUE),3),
ex_Kpct = round(mean(bat_Kpct,na.rm = TRUE),1),
ex_BBpct = round(mean(bat_BBpct ,na.rm = TRUE),1),
ex_barrelpct = round(mean(bat_barrelpct,na.rm=TRUE),1),
wOBA_value = sum(woba_value, na.rm = TRUE),
xwOBA_value = sum(xwoba_value,na.rm = TRUE),
PA = sum(woba_denom, na.rm = TRUE),
wOBA = round(wOBA_value / PA,3),
xwOBA = round(xwOBA_value / PA,3),
Kpct = round(sum(K_FL,na.rm=TRUE)/PA*100,1),
BBpct = round(sum(BB_FL ,na.rm=TRUE)/PA*100,1))
#gtで表にする
Runner_bat %>% select(Runner_1b,PA) %>% gt()
Runner_bat %>% select(Runner_1b,wOBA,ex_wOBA) %>% gt()
Runner_bat %>% select(Runner_1b,xwOBA,ex_xwOBA) %>% gt()
この記事が気に入ったらサポートをしてみませんか?