打球の速度と角度を組み合わせた価値を可視化する
打球の速度と角度の両方を考慮する必要性
打球の性質を表す指標で現在取得可能なデータとして打球速度と打球角度がある。野球に関する報道ではある選手が打球速度〇km/hの打球を放った、統計上は打球角度〇度以上の打球が理想だ、とそれぞれの指標について単体で語られることがあるが実際に打球の価値を決めるのは両者を組み合わせたものである。詳しくは後述するが例えば打球速度が170キロ出ていようと打球の角度が低ければ本塁打にはならないし打球角度が20-29度でも速度が150キロに満たなければ高い価値は生み出せない。どちらかの情報が欠けていると打球の価値を推定することは困難であり両者を使える環境にあるのならば両者を使って価値を推定することが望ましい。
打球の速度と角度を組み合わせた価値を計算する
打球の速度と角度の両者を考慮するために実際に打球の速度と角度を組み合わせた価値を計算する。計算方法は単純に各速度と各角度の組み合わせで起きたイベントを基に各指標の計算を行う。例えば出塁率なら打球速度140km/h、打球角度20度の組み合わせで起きた全イベントから出塁数と打球数を算出し出塁数を打球数で割ることで打球速度140km/h、打球角度20度の組み合わせの出塁率を算出する。こういった計算を各角度と速度で行う。
打球の速度と角度を組み合わせた価値を可視化する
しかしこうした計算を単純に行い1つ1つの数字を見ただけでは打球の速度と角度の組み合わせの概観はつかみにくい。そこで行った計算結果をグラフで可視化する。ここではバントとファウルを除いた打球について速度は1km/h、角度は1度ずつ分割したものを散布図にし各プロットにカラースケールを行った。以下に結果を示す。
出塁率
最初に出塁率を見ていく。(ここでの出塁率は公式記録上の出塁率とは異なり失策による出塁や野手選択による出塁を含んでいる。)出塁率の特徴としては打球角度が0-20度の範囲内にある打球は速度に関わらず高い出塁率を記録していることが挙げられる。特にライナー性の打球である10-20度は高い出塁率を記録している。一方で角度0度を下回るような極端に角度の低いゴロは出塁率が低い。「転がせば何かが起こる」と言われるがプロのレベルでは失策による出塁も含めても角度0度未満のゴロはチャンスが少ないようだ。また打球角度20度を超えるようなフライも打球速度が150キロ後半を超えないと出塁率は低い。鋭い角度のゴロやライナーではなくフライを打って出塁するには打球の速度との両立が必要なようだ。
本塁打/打球
続いては本塁打/打球についてみていく。まず本塁打を打つには速度によってその範囲は変わるもののある程度の打球角度が求められる。ランニングホームランのような例外を除けばホームランを打つにはフェンスを超す必要があることを考えればこれは妥当だろう。また打球速度は160km/h以上を超えたあたりから発生の頻度が高まる。本塁打は速度と角度の両立をしなければ実現不可能な代物だ。
wOBAcon
最後にwOBAconを見ていく。野球の試合で勝利するには相手より多く得点をとることが必要だ。ここまで見てきた出塁率や本塁打は得点をとる手段でありそれ自体が目的ではない。wOBAは各イベントの加重が得点価値に基づいて行われており得点への影響を測る指標としては現状ベターな選択肢と言える。(得点への相関が高いと言われる指標としてはOPSがあるがOPSは得点価値と比較して出塁を過小評価しているという問題がありあえて使う必要性がない)
wOBAconの特徴としては打球速度に関わらず角度10度~20度の打球価値が安定して高い。この打球角度は前述した出塁率の高い角度と一致しており高い出塁率が打球の価値を支えていると思われる。また打球速度が160キロを超えたあたりから20度以上の打球角度の価値が大きく上昇している。これも出塁率が高くなる組み合わせと一致している。最後に160キロ中盤で打球角度が20度を超えたあたりの価値が飛びぬけて高い。これは本塁打が出やすいゾーンと一致している。高い確率での本塁打の発生が価値を大きく底上げしているようだ。
まとめ
以上のようにいくつかの要素について打球の速度と角度の両者を見てきたが打球の価値を推定するにはどちらか単体を考慮するよりは両者を考慮したほうが良い推定ができそうだ。
library(tidyverse)
#dfには2015-2020のstatcastのデータが入っている。
#必要な列に絞る。
df <- df %>%
select(launch_angle,launch_speed,type,woba_denom,woba_value,events,des,delta_run_exp)
df <- df %>%
filter(type == "X")%>%
filter(! grepl("bunt", des))%>% # バントを除く
mutate(HR_FL = ifelse(events == "home_run",1,0),
OBP_value = case_when(
events == "single" ~ 1,
events == "double" ~ 1,
events == "triple" ~ 1,
events == "home_run" ~ 1,
events == "field_error" ~ 1,
events == "fielders_choice" ~ 1,
TRUE ~ 0),
Exit_Velocity = round(launch_speed * 1.609,0))
BattedBall_value <- df %>%
group_by(launch_angle,Exit_Velocity)%>%
dplyr::summarise(OBP = mean(OBP_value,na.rm=TRUE),
HR_pct = mean(HR_FL,na.rm=TRUE),
wOBA_denom = sum(woba_denom ,na.rm=TRUE),
wOBA_value = sum(woba_value ,na.rm=TRUE),
wOBAcon = wOBA_value / wOBA_denom,
RV = mean(delta_run_exp,na.rm=TRUE))%>%
filter(wOBA_denom >= 100)
BattedBall_value %>%
ggplot() +
geom_point(aes(x = Exit_Velocity, y = launch_angle, colour = OBP),)+
xlim(120,180)+
ylim(-40, 60)+
scale_color_gradient2(low = "blue3",mid = "white" ,high = "red",midpoint = 0.34)+
labs(title = "打球角度・速度の組み合わせ別出塁率 (MLB 15-20)",
x = "打球速度(km/h)",
y = "打球角度",
colour = "出塁率",
caption = "Source: Statcast.")
BattedBall_value %>%
ggplot() +
geom_point(aes(x = Exit_Velocity, y = launch_angle, colour = HR_pct),)+
xlim(120,180)+
ylim(-40, 60)+
scale_color_gradient2(low = "blue3",mid = "white" ,high = "red",midpoint = 0.50)+
labs(title = "打球角度・速度の組み合わせ別本塁打/打球 (MLB 15-20)",
x = "打球速度(km/h)",
y = "打球角度",
colour = "本塁打/打球",
caption = "Source: Statcast.")
BattedBall_value %>%
ggplot() +
geom_point(aes(x = Exit_Velocity, y = launch_angle, colour = wOBAcon),)+
xlim(120,180)+
ylim(-40, 60)+
scale_color_gradient2(low = "blue3",mid = "white" ,high = "red",midpoint = 0.380)+
labs(title = "打球角度・速度の組み合わせ別wOBAcon (MLB 15-20)",
x = "打球速度(km/h)",
y = "打球角度",
colour = "wOBAcon",
caption = "Source: Statcast.")
この記事が気に入ったらサポートをしてみませんか?