プルヒッターは悪なのか?

以前、プルヒッターの打球傾向を表す

Pull%(引っ張り方向の打球%)- Opp%(流し方向の打球%)

と各指標の相関を調べてみた。そのときの結果は以下のようになった。

Barrel追加

mean_angle(打球角度の平均)は相関が見られたものの他はBarrel/BBE(バレル/打球)に弱い相関が見られたぐらいだった。

ただ今思い返してみるとプルヒッターの定義は全投球に対してのPull%-Opp%でいいのだろうか。内角の投球に対して引っ張るのはコースに逆らわない打撃だが全投球に対してのPull%だとそれも含んでしまう。そこで外角の投球に限定した引っ張り率(Pull%-Opp%)で検証し直すことにした。

検証

2015-2020のMLBで通算外角打球数300以上の打者の Pull% - Opp%を算出し各種指標の相関係数を見ていく。外角の定義はプレートの中心から7cm以上外角によっている投球を対象とする。データはStatcastを使用している。

右打者

画像2

全体のPull% - Opp%のときよりも相関の上がった指標が出ている。

見てみるとContact%に負の相関、SwStr%、K%に弱い正の相関が出ており外角の投球を引っ張りにいく打者と言うのはコンタクトに難を抱える傾向があるように思われる。一方でwOBAcon、barrel/BBEは正の相関が出ており打球の価値は高い傾向にあるようだ。mean_angle(平均打球角度)は正の相関があり引っ張りにかかる打者ほど高い打球角度をもっているようだ。

打者の総合的な得点創出を表すwOBAとの相関はあまりない。コンタクトのマイナスと打球の価値のプラスが相殺しあった、ということだろうか。

左打者

画像3

左打者は右打者よりコンタクトに難がある、打球の価値が高いという傾向がより顕著に表れている。barrel/BBEはそれなりに相関があり外角の球でも引っ張りにいくような打者はそれなりにbarrelを生み出しているようだ。右打者との違いとして平均打球速度(mean_velo)が右打者は(0.11)程度だったのが左打者は(0.36)程度と弱い相関がある。左打者の方がよりコンタクトに難があるものの引っ張った時により強い打球を放ちやすい、といった傾向にあるようだ。

右打者と同じく打者の総合的な得点創出を表すwOBAとの相関はあまりない。

まとめ

打者ごとの外角の投球に対しての引っ張り率には

・Contact%に負の相関、SwStr%、K%に正の相関が見られた。外角の投球を引っ張る打者はコンタクトに難を抱える傾向にある。

・wOBAcon、barel/BBEに正の相関が見られた。外角の投球を引っ張る打者は打球の価値が高い傾向にある、

・wOBAには相関が見られなかった。

筆者には外角の投球に対してでも引っ張りにかかる打者、いわゆるプルヒッターは不器用な打者でバッティングが荒いイメージがあり、逆にコースに逆らわないようなスプレーヒッターは器用で洗練された優れた打者というイメージがあった。実際数字で見てみても外角の投球を引っ張る打者ほどコンタクトが低い傾向にある。ただ一方でプルヒッターは打球の価値を上げることには優れている。外角への投球でもプルヒッティングを試みるような打者はパワーに自信がありそれを活かすためにあえてプルヒッティングを行っているのかもしれない。総合的な得点創出では特に相関は見られないところからプルヒッターとスプレーヒッター、どちらかが優れているということはなさそうだ。

以下、今回書いたRのコード。

#tidyverseを使用
library(tidyverse)
#dfには2015-2020のレギュラーシーズンのデータが入っている
#必要なデータに絞る
df <- df%>%
 select(events, type,des,description,stand,woba_value,
        woba_denom,pitcher,player_name,hc_x,hc_y,
        plate_x,launch_angle,launch_speed,barrel)
save(df, file="sc_data_for_pull_contact.Rdata")

#データの下処理
strikeouts <- c("strikeout", "strikeout_double_play")
df <- df %>% mutate(
 K_FL = ifelse(events %in% strikeouts, 1, 0),
 spray_angle =  atan2(hc_x - 125.42, 198.27 - hc_y) * 180 / pi, 
 hand_adj_spray = 
   ifelse(stand == "L", - spray_angle, spray_angle),
 Pull_FL = ifelse(hand_adj_spray <= -17, 1,0),
 Cent_FL = ifelse(hand_adj_spray > -17 & hand_adj_spray < 17 , 1, 0),
 Opp_FL = ifelse(hand_adj_spray >= 17, 1, 0),
 #コースをcmに変換、左右で内外の値を揃える
 plate_x_r_cm = plate_x * 30.48,
 plate_x_cm = ifelse(stand == "R",plate_x_r_cm,-1 * plate_x_r_cm),
 #投球、バント除く
 pitch_denom = case_when(
   description == "swinging_strike" ~ "1",
   description == "swinging_strike_blocked" ~ "1",
   description == "called_strike" ~ "1",
   description == "foul_tip" ~ "1",
   description == "bunt_foul_tip" ~ "0",
   description == "foul" ~ "1",
   description == "foul_bunt" ~ "0",
   description == "ball" ~ "1",
   description == "blocked_ball" ~ "1",
   description == "pitchout" ~ "0",
   description == "hit_by_pitch" ~ "1",
   description == "hit_into_play" ~ "1",
   description == "hit_into_play_score" ~ "1",
   description == "hit_into_play_no_out" ~ "1",
   description == "missed_bunt" ~ "0"),
 pitch_denom = as.double(pitch_denom),
 #スウィング、バント除く
 swing = case_when( 
   description == "swinging_strike" ~ "1",
   description == "swinging_strike_blocked" ~ "1",
   description == "called_strike" ~ "0",
   description == "foul_tip" ~ "1",
   description == "bunt_foul_tip" ~ "0",
   description == "foul" ~ "1",
   description == "foul_bunt" ~ "0",
   description == "ball" ~ "0",
   description == "blocked_ball" ~ "0",
   description == "pitchout" ~ "0",
   description == "hit_by_pitch" ~ "0",
   description == "hit_into_play" ~ "1",
   description == "hit_into_play_score" ~ "1",
   description == "hit_into_play_no_out" ~ "1",
   description == "missed_bunt" ~ "0"),
 swing = as.double(swing),
 #コンタクト、バント除く
 contact = case_when( 
   description == "swinging_strike" ~ "0",
   description == "swinging_strike_blocked" ~ "0",
   description == "called_strike" ~ "0",
   description == "foul_tip" ~ "0",
   description == "bunt_foul_tip" ~ "0",
   description == "foul" ~ "1",
   description == "foul_bunt" ~ "0",
   description == "ball" ~ "0",
   description == "blocked_ball" ~ "0",
   description == "pitchout" ~ "0",
   description == "hit_by_pitch" ~ "0",
   description == "hit_into_play" ~ "1",
   description == "hit_into_play_score" ~ "1",
   description == "hit_into_play_no_out" ~ "1",
   description == "missed_bunt" ~ "0"),
 contact = as.double(contact),
 #空振り、バント除く
 swst = case_when( 
   description == "swinging_strike" ~ "1",
   description == "swinging_strike_blocked" ~ "1",
   description == "called_strike" ~ "0",
   description == "foul_tip" ~ "1",
   description == "bunt_foul_tip" ~ "0",
   description == "foul" ~ "0",
   description == "foul_bunt" ~ "0",
   description == "ball" ~ "0",
   description == "blocked_ball" ~ "0",
   description == "pitchout" ~ "0",
   description == "hit_by_pitch" ~ "0",
   description == "hit_into_play" ~ "0",
   description == "hit_into_play_score" ~ "0",
   description == "hit_into_play_no_out" ~ "0",
   description == "missed_bunt" ~ "0"),
 swst = as.double(swst))

#外角の打球数300の引っ張り率-逆方向率を算出
outside_pull_R <- df %>%
 filter(stand == "R",plate_x_cm >= 7 ,type == "X")%>%
 group_by(player_name)%>%
 dplyr::summarise(
   wOBAcon_denom = sum(woba_denom, na.rm = TRUE),
   Pullpct = sum(Pull_FL, na.rm = TRUE)/wOBAcon_denom * 100,
   Opppct = sum(Opp_FL, na.rm = TRUE)/wOBAcon_denom * 100,
   Outside_Pull_minus_Opp = Pullpct - Opppct)
outside_pull_R <- outside_pull_R %>% filter(wOBAcon_denom >= 300)
outside_pull_R <- outside_pull_R %>% select(player_name,Outside_Pull_minus_Opp)

#各種指標算出
standard_stats <- df %>%
 filter(stand == "R") %>%
 group_by(player_name)%>%
 dplyr::summarise(
   pitch_denom = sum(pitch_denom, na.rm = TRUE),
   swing = sum(swing, na.rm = TRUE),
   contact = sum(contact, na.rm = TRUE),
   swst = sum(swst, na.rm = TRUE),
   swingpct = swing / pitch_denom * 100,
   contactpct = contact / swing * 100,
   swstpct = swst / pitch_denom * 100,
   PA = sum(woba_denom, na.rm = TRUE),
   K = sum(K_FL, na.rm = TRUE),
   wOBA_value = sum(woba_value, na.rm = TRUE),
   Kpct = K / PA * 100,
   wOBA = wOBA_value / PA)%>%
 select(player_name,swingpct,contactpct,swstpct,Kpct,wOBA)
 
 #打球系各種指標算出
standard_statsX <- df %>%
 filter(stand == "R",type == "X") %>%
 group_by(player_name)%>%
 dplyr::summarise(
   wOBAcon_denom = sum(woba_denom, na.rm = TRUE),
   wOBAcon_value = sum(woba_value, na.rm = TRUE),
   wOBAcon = wOBAcon_value / wOBAcon_denom,
   barrel_CT = sum(barrel, na.rm = TRUE),
   barrel_BBE = barrel_CT / wOBAcon_denom,
   mean_angle = mean(launch_angle, na.rm = TRUE),
   mean_velo = mean(launch_speed, na.rm = TRUE))%>%
 select(player_name,wOBAcon,barrel_BBE,mean_angle,mean_velo)
 
 #列を結合してcsvで保存
hitter_R <- left_join(outside_pull_R,standard_stats,by="player_name")
hitter_R <- left_join(hitter_R,standard_statsX,by="player_name")
write_csv(hitter,"hitter_R.csv")

#左打者も同様に行う
outside_pull_L <- df %>%
 filter(stand == "L",plate_x_cm >= 7 ,type == "X")%>%
 group_by(player_name)%>%
 dplyr::summarise(
   wOBAcon_denom = sum(woba_denom, na.rm = TRUE),
   Pullpct = sum(Pull_FL, na.rm = TRUE)/wOBAcon_denom * 100,
   Opppct = sum(Opp_FL, na.rm = TRUE)/wOBAcon_denom * 100,
   Outside_Pull_minus_Opp = Pullpct - Opppct)
outside_pull_L <- outside_pull_L %>% filter(wOBAcon_denom >= 300)
outside_pull_L <- outside_pull_L %>% select(player_name,Outside_Pull_minus_Opp)

standard_stats_L <- df %>%
 filter(stand == "L") %>%
 group_by(player_name)%>%
 dplyr::summarise(
   pitch_denom = sum(pitch_denom, na.rm = TRUE),
   swing = sum(swing, na.rm = TRUE),
   contact = sum(contact, na.rm = TRUE),
   swst = sum(swst, na.rm = TRUE),
   swingpct = swing / pitch_denom * 100,
   contactpct = contact / swing * 100,
   swstpct = swst / pitch_denom * 100,
   PA = sum(woba_denom, na.rm = TRUE),
   K = sum(K_FL, na.rm = TRUE),
   wOBA_value = sum(woba_value, na.rm = TRUE),
   Kpct = K / PA * 100,
   wOBA = wOBA_value / PA)%>%
 select(player_name,swingpct,contactpct,swstpct,Kpct,wOBA)
 
standard_statsX_L <- df %>%
 filter(stand == "L",type == "X") %>%
 group_by(player_name)%>%
 dplyr::summarise(
   wOBAcon_denom = sum(woba_denom, na.rm = TRUE),
   wOBAcon_value = sum(woba_value, na.rm = TRUE),
   wOBAcon = wOBAcon_value / wOBAcon_denom,
   barrel_CT = sum(barrel, na.rm = TRUE),
   barrel_BBE = barrel_CT / wOBAcon_denom,
   mean_angle = mean(launch_angle, na.rm = TRUE),
   mean_velo = mean(launch_speed, na.rm = TRUE))%>%
 select(player_name,wOBAcon,barrel_BBE,mean_angle,mean_velo)
 
hitter_L <- left_join(outside_pull_L,standard_stats_L,by="player_name")
hitter_L <- left_join(hitter_L,standard_statsX_L,by="player_name")
write_csv(hitter,"hitter_L.csv")

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