平均角度をdisるような話を長々と書いてきたが, ということは他に考えるべき変数があるということでもある. 打球の速度や角度については平均が最も語られるが, これらの数値は実際の打球の性質を考慮する上では十分とはいえないであろうことは概ね明らかである. 今回は考えるべき他の変数として速度と角度の標準偏差 (SD) について扱う. 基本的には分布の幅を考えられる変数であれば, 別にSDである必要性は無いのだが, 最も素直な選択肢だというところだろう. 現実にはSDよりももっと良い変数もありうるだろう.
これらの要素がなぜ重要と考えられるかについては, Eli Ben-Poratが既に詳しく説明してくれている. まずこの議論に乗って, なぜ分布の幅が重要となるかについて説明する.
下の図は打球の角度を2.5°ずつグループ化して, その中の平均的な打球の価値と打球の数を示している.
これは平均的な打者の角度に沿った打球の価値と数の分布と考えることができる. ここで, 価値の分布と打球数の分布との中心は比較的近いところにあり, 打者が価値の高い領域に合わせて打球角度を合わせていることが予想される. s分布の広がりは打球数のほうが大きく, 分布の裾は価値の低い打球が多くなる. そのため, 打球角度の広がりを小さくすれば, つまり角度のばらつきを小さくすれば, より価値のある打球が多くなる.
一方, 下は速度に関して同様な図を作成した.
速度の場合では, 打球数のピークは打球価値のピークとは一致せず, あまり価値がないところに位置している. このため, “同じ打球速度であれば”, 分布の広がりが大きいほど, 速度のばらつきが大きいほど, 価値の高い右側の打球が増える可能性がある.
彼はこのような背景から以下の指標を提案している.
\[TROUT = \frac{平均速度 * 速度のSD}{角度のSD}\]
ばらつきを示す代表的な統計量としてSDが利用されている. 同じ打球速度であれば速度のばらつきが大きいほど大きくなり, また角度のばらつきが小さいほど大きくなるような設計になっている (平均角度は無視されているが, これは平均的にすでに適した部分にあるためだろう; あくまで説明の道具という部分があり重み付け的な部分は適当だと思われる). 指標の名前は彼の計算したランキングでTroutが目立ったことにちなんでいる. 2017年Troutは打球速度はあまり大きくないにも関わらず, 例年通り生産性が高かったことが速度と角度のSDによって説明されるのかもしれないと考えているようだ.
しかし, Ben-Poratは角度のSDが低下することによってBABIPがわずかに変化する可能性は示しているが, 速度や角度のSDが打球価値の変化につながるかについて十分に明らかにできていない. 打球価値に影響を与える要素が複数あるにも関わらず, それらの要因を調整せずに角度のSDだけで説明を試みたために感度が低くなってしまっているだと思われる. というわけで, この点を検討する.
# dataは18-10-02取得
require(mgcv)
require(cowplot)
require(knitr)
require(reshape2)
require(coefplot)
require(car)
require(corrplot)
library(GGally)
require(tidyverse)
typeX <- df2 %>%
filter(type == "X")%>%
filter(! grepl("bunt", des))%>% # bunt除く 全部は除けてないかも
mutate(bb_FL = ifelse(type == "X", 1, 0),
PU_FL = ifelse(bb_type == "popup", 1, 0),
FB_FL = ifelse(bb_type == "fly_ball", 1, 0),
GB_FL = ifelse(bb_type == "ground_ball", 1, 0),
LD_FL = ifelse(bb_type == "line_drive", 1, 0),
HR_FL = ifelse(events == "home_run", 1, 0),
xWOBA_value = ifelse(type == "X", estimated_woba_using_speedangle, woba_value))
bat <- typeX %>%
group_by(player_name)%>%
dplyr::summarise(speed_mean = mean(launch_speed, na.rm = TRUE),
speed_sd = sd(launch_speed, na.rm = TRUE),
angle_mean = mean(launch_angle, na.rm = TRUE),
angle_sd = sd(launch_angle, na.rm = TRUE),
wOBA_value = sum(woba_value, na.rm = TRUE),
xwOBA_value = sum(xWOBA_value, na.rm = TRUE),
wOBA_denom = sum(woba_denom, na.rm = TRUE),
wOBA = wOBA_value / wOBA_denom,
xwOBA = xwOBA_value / wOBA_denom,
iso = sum(iso_value, na.rm = TRUE) / wOBA_denom, # ISOcon
HR_BBE =sum(HR_FL, na.rm = TRUE) / wOBA_denom,
GB_BBE = sum(GB_FL, na.rm = TRUE)/ wOBA_denom,
FB_BBE = sum(FB_FL, na.rm = TRUE)/ wOBA_denom,
LD_BBE = sum(LD_FL, na.rm = TRUE)/ wOBA_denom,
PU_BBE = sum(PU_FL, na.rm = TRUE)/ wOBA_denom,
barrel_CT = sum(barrel),
barrel_rate = barrel_CT / wOBA_denom)%>%
filter(wOBA_denom >= 300) # 打球数
bat2 <- typeX %>%
group_by(player_name, game_year)%>%
dplyr::summarise(speed_mean = mean(launch_speed, na.rm = TRUE),
speed_sd = sd(launch_speed, na.rm = TRUE),
angle_mean = mean(launch_angle, na.rm = TRUE),
angle_sd = sd(launch_angle, na.rm = TRUE),
wOBA_value = sum(woba_value, na.rm = TRUE),
xwOBA_value = sum(xWOBA_value, na.rm = TRUE),
wOBA_denom = sum(woba_denom, na.rm = TRUE),
wOBA = wOBA_value / wOBA_denom,
xwOBA = xwOBA_value / wOBA_denom,
iso = sum(iso_value, na.rm = TRUE) / wOBA_denom, # ISOcon
HR_BBE =sum(HR_FL, na.rm = TRUE) / wOBA_denom,
GB_BBE = sum(GB_FL, na.rm = TRUE)/ wOBA_denom,
FB_BBE = sum(FB_FL, na.rm = TRUE)/ wOBA_denom,
LD_BBE = sum(LD_FL, na.rm = TRUE)/ wOBA_denom,
PU_BBE = sum(PU_FL, na.rm = TRUE)/ wOBA_denom,
barrel_CT = sum(barrel),
barrel_rate = barrel_CT / wOBA_denom)%>%
filter(wOBA_denom >= 200) # 打球数
まず, 連続した年度で打球数 (BBE) 200以上の選手に関して, 速度や角度に関連した指標の年度間相関を示す.
years <- 2015:2017
df.xy <- NULL
for(i in years){
df.x <- bat2 %>%
filter(game_year == i)
df.y <- bat2 %>%
filter(game_year == i + 1)
temp <- inner_join(df.x, df.y, by = "player_name")
df.xy <- rbind(df.xy, temp)
}
YtY.cor <- data.frame(value = "r",
`速度平均` = cor.test(df.xy$speed_mean.x, df.xy$speed_mean.y)$estimate,
`速度SD` = cor.test(df.xy$speed_sd.x, df.xy$speed_sd.y)$estimate,
`角度平均` = cor.test(df.xy$angle_mean.x, df.xy$angle_mean.y)$estimate,
`角度SD` = cor.test(df.xy$angle_sd.x, df.xy$angle_sd.y)$estimate,
wOBAcon = cor.test(df.xy$wOBA.x, df.xy$wOBA.y)$estimate)
YtY.cor %>%
mutate_if(is.numeric, funs(round), 3)%>%
kable()
value | 速度平均 | 速度SD | 角度平均 | 角度SD | wOBAcon |
---|---|---|---|---|---|
r | 0.737 | 0.46 | 0.812 | 0.696 | 0.548 |
速度平均, 角度平均, 角度SDはかなり相関が高い. 速度のSDはやや低いがそれでもwOBAconとそれほどの差は無い程度. 選手間でこれらの変数を制御する能力に違いがある可能性が高いだろう.
仮に平均値とSDの間に強い相関があるのであれば, 別々に考える意味は小さい. まず各打者の平均角度と角度のSDの間の関係を散布図で示す. 以後は15-18で300BBE以上.
非常に相関は弱く, 平均角度が大きいが角度のSDが小さい選手や, 平均角度が小さいがSDが大きい選手もおり, 分けて考える意義があるといえるかもしれない. 角度のSDが小さい打者でwOBAconが高いかもしれない? それほどはっきりとした傾向は見えないと言っておくべきだろう.
角度に比べれば相関が強いようだが, やはりそれほど大きな相関ではなく, 別々に考える意義があるかもしれない. 角度のSDが小さい打者でwOBAconが高いかもしれない? これもそれほどはっきりとした傾向は見えない.
冒頭の議論から, 角度と速度のSDの低下は打球価値と関連がある可能性がある. 打球の価値と関連があり, また打球角度との関連が予想される要素としては, FB, LD, GB, PUの打球タイプ分類がある. そこで打球タイプの分類を利用し, それらの頻度に対する一部の変数の影響をおおまかに検討する.
打球角度の平均とSDに注目して, 打球タイプとの関係を可視化する.
GB%との関係.
角度が下がるとGB%が上昇する. SDはあまり効いていないのではないか.
FB%との関係.
これも平均が主に効いているだろう. SDはあまり関係ないのでは.
LD%.
これは平均角度はあまり効いていない. 一応中央付近 (12.5°ほど) に持っていくと多少上がっていたようだが. ここではSDの傾向が顕著に出ている.
軸を入れ替える.
SDが低下するほどLD%が増加していたのがわかる. 角度のSDが調整された状態では平均角度も影響があったらしいことも見て取れる.
PU%との関係.
平均角度も効いているが, SDも効いている. こちらも軸を入れ替えてみる.
軸を入れ替えてもLDほど劇的な変化はない. 平均とSDが半々ぐらい?
散布図から角度SDと打球タイプの大まかな関係 (平均角度で調整された状態) をまとめると,
角度のSDは打球タイプを考える上では, 重要な要因の一つであるようだ.
同様に速度の平均とSDについて可視化. ただし, 速度と打球タイプの間に直接関連があるかどうかは普通に考えればあやしい. 仮に効果があるように見えたとしても, 2次的な効果だと思われるが, 比較のため一応確認するという程度. 基本的には飛ばしてもらって構わないが, あとで言及する.
GB%との関係.
速度が遅いほどGB%が高い. 低く打つことで速度が遅くなるとは思えないので, おそらく力のない打者がGBを選択的に打っているのだろう (速度遅い→GBを打つ). もしそうであれば, 後で見るようにFBの価値は速度に強く依存するので, 判断としては理に適っている.
SDの大きい打者でGB%が少し多い傾向があるかもしれないが解釈は困難.
FB%との関係.
速度が早いほどFB%が高い. これも打球速度からの選手自身の選択の結果だろう.
LD%との関係.
平均とは明確な関連は見えない. 速度のSDが大きい選手はLD%が低かったようだ. 極端に早い打球や遅い打球が少ない選手はコンタクトに優れているように思われ, そのような打者でLDが多いというのは直感的にもありそうな話だが, メカニズム的に意味があるというよりは選択の結果のように思われる.
PU%との関係.
あまり変わらないように見える.
平均と速度についてまとめると,
速度のSDはそれほど関連がなさそう? そもそも解釈が困難.
速度について見てきたが, 解釈は困難である. まず, メカニズム的な関連がはっきりしない. さらに, ここでは角度に関して調整がなされていない. ある打球を分類しようと考える場合, 角度は特に重要な要因になるだろうと考えられる. 実際に上で見たとおり, 角度と打球タイプとの相関はかなり強い. 打者自身の選択を介して速度と角度に相関があるために, 速度との疑似相関がみえている可能性が考えられる.
より詳細に各変数間の影響を排除する必要性があるだろう. 図で示すのは限界があり, 変数が多くなると困難である.
各パラメータの影響を調整した状態での影響を調べるために, 単純な方法として重回帰モデルで説明させてみる.
各打球タイプ%について,
モデル1. 角度と速度について, 平均とSD (4説明変数)
モデル2. 角度と速度について, 平均のみ (2説明変数)
で重回帰モデルをつくり結果を比較する.
正直なところ速度系の変数から影響がありそうな結果になっても解釈の仕様がないように思えるため, いれなくていいような気もするが, とりあえず入れて偏回帰係数を見ておきたい. ぶっちゃけると, あとで打球価値との関係も同様に重回帰にぶち込むのでそのあたりとの比較の意図が大きい. また, 単純な1次の線形回帰を行うので, 各変数の効果が直線的で, かつ加法的であるべきだが, これが満たされているかどうかはやや怪しいかもしれない.
影響の大きさを比較しやすくするために正規化したデータを用意し, 説明変数間の相関を図で示す.
fit_data1 <- bat %>%
dplyr::select(GB_BBE,FB_BBE, LD_BBE, PU_BBE, speed_mean, speed_sd, angle_mean, angle_sd)
# データを正規化する
# 偏回帰係数の比較が容易になる
fit_data1 <- scale(fit_data1)
fit_data1 <- data.frame(fit_data1)
ggpairs(fit_data1[,5:8],
aes_string(alpha=0.6),
lower=list(continuous=wrap("points",size=0.05))
)+
theme(strip.text= element_text(size=10))
説明変数間に弱い相関があるので解釈には注意が必要だろう.
GB%について重回帰モデルを作り, 結果の要約を示す.
# 正規化済み
gb_multi1 <- lm(GB_BBE ~ speed_mean + speed_sd + angle_mean + angle_sd,
data = fit_data1)
gb_multi2 <- lm(GB_BBE ~ speed_mean + angle_mean ,
data = fit_data1)
# モデル1
summary(gb_multi1)
##
## Call:
## lm(formula = GB_BBE ~ speed_mean + speed_sd + angle_mean + angle_sd,
## data = fit_data1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.91242 -0.13003 0.00407 0.13471 0.69786
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -2.258e-17 1.000e-02 0.000 1.000000
## speed_mean -4.298e-02 1.096e-02 -3.921 0.000102 ***
## speed_sd -6.641e-03 1.132e-02 -0.587 0.557597
## angle_mean -9.781e-01 1.034e-02 -94.626 < 2e-16 ***
## angle_sd 5.909e-02 1.077e-02 5.484 6.86e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.2157 on 460 degrees of freedom
## Multiple R-squared: 0.9539, Adjusted R-squared: 0.9535
## F-statistic: 2378 on 4 and 460 DF, p-value: < 2.2e-16
# モデル2
summary(gb_multi2)
##
## Call:
## lm(formula = GB_BBE ~ speed_mean + angle_mean, data = fit_data1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.94872 -0.13249 0.00225 0.14259 0.78960
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.755e-17 1.032e-02 0.000 1
## speed_mean -4.822e-02 1.044e-02 -4.621 4.97e-06 ***
## angle_mean -9.670e-01 1.044e-02 -92.670 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.2225 on 462 degrees of freedom
## Multiple R-squared: 0.9507, Adjusted R-squared: 0.9505
## F-statistic: 4455 on 2 and 462 DF, p-value: < 2.2e-16
AIC(gb_multi1, gb_multi2)
## df AIC
## gb_multi1 6 -99.95824
## gb_multi2 4 -72.98670
1と2ともに非常に高いadjusted R^2となっている. SDを入れてもほとんど変わらない.
SDも含めたモデルでは平均速度以外の変数は有意という結果になったが, 偏回帰係数の点推定値 (Coefficients: Estimate) を見る限りほとんどは平均角度の影響だろう.
それぞれのモデルの偏回帰係数をプロットする.
multiplot(gb_multi1, gb_multi2) +
theme_classic(base_family = "HiraKakuPro-W3")+
labs(title = "GB%重回帰モデル",
subtitle = "説明変数は正規化済み.")
平均角度のvalueは概ね-1となっているが, ここではデータを正規化しているため, これは平均角度が1SD分上昇すると, 他の変数が固定された状態では, GB%は約1SD分低下することを意味する. 平均角度の直接的な影響が大きい可能性が高いだろうという直感的な結果.
打球速度の平均をx軸にとった散布図ではGB%と相関がありそうだったが (平均速度 vs GB%の図), ここでは打球速度はほとんど影響が無いと推定されている. これは, ここで考慮に入れた変数との相関が要因であのような関係が観察された可能性を示している. 偏回帰係数を見る限り, 平均角度がとの相関が原因だろうと考えられる. 平均速度と平均角度の相関はそれほどかなり小さい (r = 0.14) が, 平均角度のGB%への影響の大きさのため, 平均速度に注目すると相関があるように見えてしまったのだろう.
多重共線性をチェック.
vif(gb_multi1)
## speed_mean speed_sd angle_mean angle_sd
## 1.198733 1.277408 1.065731 1.157635
問題ないのでは.
同様にFBで重回帰.
##
## Call:
## lm(formula = FB_BBE ~ speed_mean + speed_sd + angle_mean + angle_sd,
## data = fit_data1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.56917 -0.28027 -0.01902 0.24147 1.45256
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -4.887e-17 1.870e-02 0.000 1.00000
## speed_mean 1.932e-01 2.050e-02 9.428 < 2e-16 ***
## speed_sd 2.362e-02 2.116e-02 1.116 0.26489
## angle_mean 8.749e-01 1.933e-02 45.271 < 2e-16 ***
## angle_sd -6.653e-02 2.014e-02 -3.303 0.00103 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.4033 on 460 degrees of freedom
## Multiple R-squared: 0.8388, Adjusted R-squared: 0.8374
## F-statistic: 598.3 on 4 and 460 DF, p-value: < 2.2e-16
##
## Call:
## lm(formula = FB_BBE ~ angle_mean + speed_mean, data = fit_data1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.52873 -0.26186 -0.02679 0.25547 1.43846
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -9.605e-17 1.888e-02 0.00 1
## angle_mean 8.619e-01 1.909e-02 45.14 <2e-16 ***
## speed_mean 2.049e-01 1.909e-02 10.73 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.4071 on 462 degrees of freedom
## Multiple R-squared: 0.835, Adjusted R-squared: 0.8342
## F-statistic: 1169 on 2 and 462 DF, p-value: < 2.2e-16
## df AIC
## fb_multi1 6 481.9922
## fb_multi2 4 488.8943
これもいずれのモデルも高いadjusted R^2を示した (0.83程度). これもやはり平均角度の影響が大きい可能性が高いだろう.
平均速度が少し効いているように見えるがよくわからない. 角度の平均やSDでうまく拾えない部分の角度の影響を拾った, 間接的な効果かもしれない.
LDについて重回帰.
##
## Call:
## lm(formula = LD_BBE ~ speed_mean + speed_sd + angle_mean + angle_sd,
## data = fit_data1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.62458 -0.50564 0.01377 0.48780 3.06994
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.703e-16 3.417e-02 0.000 1.000
## speed_mean -8.893e-02 3.745e-02 -2.375 0.018 *
## speed_sd -4.385e-02 3.866e-02 -1.134 0.257
## angle_mean 2.260e-01 3.531e-02 6.399 3.85e-10 ***
## angle_sd -6.662e-01 3.680e-02 -18.101 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.7368 on 460 degrees of freedom
## Multiple R-squared: 0.4618, Adjusted R-squared: 0.4572
## F-statistic: 98.69 on 4 and 460 DF, p-value: < 2.2e-16
##
## Call:
## lm(formula = LD_BBE ~ angle_mean + speed_mean, data = fit_data1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.8245 -0.7037 -0.0443 0.6034 3.6549
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.325e-16 4.615e-02 0.000 1.0000
## angle_mean 1.043e-01 4.667e-02 2.235 0.0259 *
## speed_mean -7.218e-02 4.667e-02 -1.547 0.1226
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.9951 on 462 degrees of freedom
## Multiple R-squared: 0.01395, Adjusted R-squared: 0.009685
## F-statistic: 3.269 on 2 and 462 DF, p-value: 0.03893
## df AIC
## ld_multi1 6 1042.503
## ld_multi2 4 1320.078
モデル間の差が顕著に出た. SDを説明変数に含めたモデル1ではR^2は0.46だが, 平均だけのモデル2はR^2は0.01でほとんど説明できていないことがわかる.
角度のSDの影響が大きく, SDが小さいほどLDは増加する. 平均角度も多少は効いているのかもしれない. 正の相関であるところを見ると角度が低すぎる打者でLDが少なかった? また, 上で示した平均角度とLD%のプロット (打球角度 vs 打球タイプの平均角度 vs LD%) を見る限り, 一次式の関係でないため効果を正確に評価できていない可能性もあるかもしれない. LDの価値の高さを考えると, このモデルでは平均角度の価値がやや過小評価されているかもしれない.
PU%の重回帰.
##
## Call:
## lm(formula = PU_BBE ~ speed_mean + speed_sd + angle_mean + angle_sd,
## data = fit_data1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.75886 -0.25174 0.01474 0.22885 1.41435
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -4.059e-16 1.772e-02 0.000 1.000
## speed_mean -1.498e-01 1.943e-02 -7.709 7.92e-14 ***
## speed_sd 1.843e-02 2.005e-02 0.919 0.358
## angle_mean 5.431e-01 1.832e-02 29.651 < 2e-16 ***
## angle_sd 6.519e-01 1.909e-02 34.146 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.3822 on 460 degrees of freedom
## Multiple R-squared: 0.8552, Adjusted R-squared: 0.8539
## F-statistic: 679.1 on 4 and 460 DF, p-value: < 2.2e-16
##
## Call:
## lm(formula = PU_BBE ~ angle_mean + speed_mean, data = fit_data1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.31561 -0.49141 0.01553 0.49323 2.26915
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2.546e-17 3.487e-02 0.000 1
## angle_mean 6.629e-01 3.526e-02 18.801 < 2e-16 ***
## speed_mean -1.748e-01 3.526e-02 -4.959 9.98e-07 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.7518 on 462 degrees of freedom
## Multiple R-squared: 0.4372, Adjusted R-squared: 0.4347
## F-statistic: 179.4 on 2 and 462 DF, p-value: < 2.2e-16
## df AIC
## pu_multi1 6 432.1154
## pu_multi2 4 1059.3474
これもSDを入れることでモデルが劇的に改善した (R^2 0.44 → 0.85). モデル1では角度SDと平均角度の影響が大きい.
このように重回帰を使って打球割合を推定させると, LD%とPU%に関してはSDを説明変数に含めることでかなり改善する. このような効果は角度分布から予想される効果と整合的である. 角度のSDの低下はLDの増加とPUの低下に対してかなり効果が大きいようだ. LDは非常に価値が高い打球であり, PUは非常に価値が低い打球であるため, 角度の分布を狭く維持できれば打球価値自体の改善につながる可能性があるという考えを支持していると言えるだろう.
打球タイプへの影響は主に平均角度と角度のSDから影響が大きい可能性があり, 速度はこれらの打球タイプ自体にはあまり影響しないようだった. しかし, 速度はwOBAconとそれなりに強い相関を見せる. これは, 打球タイプを変化させるのではなく, 同じ打球タイプでもその価値を変えることでwOBAconに貢献している可能性が考えられる. この点を検討するために, 各打球タイプごとの価値を, バントを除く全打球の速度と角度の平均とSDから推定するモデルをつくる.
まず, そもそも打球タイプごとの価値の個人差がどれくらいあるか眺める (各打球タイプについて100以上) .
bb_value_by_players <- typeX%>%
group_by(player_name, bb_type)%>%
dplyr::summarise(N = sum(woba_denom, na.rm = TRUE),
wOBAcon = sum(woba_value, na.rm = TRUE)/N,
xwOBAcon = sum(estimated_woba_using_speedangle, na.rm = TRUE)/N)%>%
filter(N >= 100)
dplyr::summarise(group_by(bb_value_by_players, bb_type),
N = n(),
BBE_avg = mean(N),
mean = mean(wOBAcon),
sd = sd(wOBAcon))
## # A tibble: 4 x 5
## bb_type N BBE_avg mean sd
## <chr> <int> <dbl> <dbl> <dbl>
## 1 fly_ball 380 380 0.404 0.129
## 2 ground_ball 538 538 0.249 0.0385
## 3 line_drive 413 413 0.701 0.0651
## 4 popup 97 97 0.0249 0.0140
BBE_avgは条件を満たした選手の打球数の平均値.
打球価値の個人差はFBが圧倒的に大きい. LDがそれに続く. GBはそれほど差は大きくない. FBやLDに関してはGBより打球数も少ないので, 推定の甘さも関係しているかもしれない.
GBの打球価値wOBAconの重回帰モデル.
##
## Call:
## lm(formula = ground_ball ~ speed_mean + speed_sd + angle_mean +
## angle_sd, data = fit_data2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.9881 -0.6863 0.0195 0.6321 3.3864
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -5.639e-16 4.530e-02 0.000 1.000000
## speed_mean 4.348e-02 4.965e-02 0.876 0.381604
## speed_sd 1.799e-01 5.125e-02 3.510 0.000493 ***
## angle_mean -1.300e-01 4.681e-02 -2.777 0.005706 **
## angle_sd -1.921e-03 4.879e-02 -0.039 0.968613
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.9768 on 460 degrees of freedom
## Multiple R-squared: 0.05403, Adjusted R-squared: 0.04581
## F-statistic: 6.569 on 4 and 460 DF, p-value: 3.798e-05
##
## Call:
## lm(formula = ground_ball ~ speed_mean + angle_mean, data = fit_data2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.3177 -0.6938 0.0178 0.6603 3.7389
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -5.874e-16 4.587e-02 0.00 1.00000
## speed_mean 1.076e-01 4.639e-02 2.32 0.02080 *
## angle_mean -1.359e-01 4.639e-02 -2.93 0.00355 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.9891 on 462 degrees of freedom
## Multiple R-squared: 0.0259, Adjusted R-squared: 0.02169
## F-statistic: 6.143 on 2 and 462 DF, p-value: 0.002328
## df AIC
## gb_woba_multi1 6 1304.783
## gb_woba_multi2 4 1314.408
いずれのモデルもほとんど説明できていない. この理由としては, 重要な要因であろう走力や, 打席の左右が考慮されていないことが一つかもしれない. また, そもそも上で示したように個人間での差が小さく, 大部分は偶然によって生じた差である可能性もありそうである.
平均速度と関連が無いというのはやや不思議な結果かもしれない. 遅い打球と早い打球が安打になりやすいなどの曲線的な傾向があれば, このモデルでは正しく評価されないので, このあたりが原因かもしれない. また, 平均角度の低下はwOBAconの改善と関連があったようだ. このあたりは, これは考慮に入っていない走力との間接的な相関を含めた形で偏回帰係数が推定されている可能性もあるだろう.
次にFB wOBAconとの関係.
##
## Call:
## lm(formula = fly_ball ~ speed_mean + speed_sd + angle_mean +
## angle_sd, data = fit_data2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.67591 -0.40354 -0.03201 0.36138 1.57001
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.08287 0.03110 -2.665 0.00804 **
## speed_mean 0.52441 0.03407 15.394 < 2e-16 ***
## speed_sd 0.44261 0.03606 12.273 < 2e-16 ***
## angle_mean 0.15857 0.03174 4.995 9.04e-07 ***
## angle_sd -0.09261 0.03308 -2.799 0.00539 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.5992 on 373 degrees of freedom
## (87 observations deleted due to missingness)
## Multiple R-squared: 0.6448, Adjusted R-squared: 0.641
## F-statistic: 169.3 on 4 and 373 DF, p-value: < 2.2e-16
##
## Call:
## lm(formula = fly_ball ~ speed_mean + angle_mean, data = fit_data2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.69767 -0.49226 -0.02003 0.47513 1.97561
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.08273 0.03680 -2.248 0.025152 *
## speed_mean 0.68708 0.03714 18.501 < 2e-16 ***
## angle_mean 0.12714 0.03677 3.457 0.000608 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.7093 on 375 degrees of freedom
## (87 observations deleted due to missingness)
## Multiple R-squared: 0.4996, Adjusted R-squared: 0.4969
## F-statistic: 187.2 on 2 and 375 DF, p-value: < 2.2e-16
## df AIC
## fb_woba_multi1 6 692.4675
## fb_woba_multi2 4 818.0208
やはり最も偏回帰係数の絶対値が大きいのは平均速度だった. これに加えて, 速度のSDもやや正の関連が強く, FB wOBAconの推定はSDを含めたモデル1でR^2やAICの改善が見られた. この結果は冒頭の議論と整合的である.
LDの価値との関係.
##
## Call:
## lm(formula = line_drive ~ speed_mean + speed_sd + angle_mean +
## angle_sd, data = fit_data2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.13459 -0.44052 0.02803 0.39166 2.17787
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.02231 0.03315 -0.673 0.50126
## speed_mean 0.54964 0.03662 15.010 < 2e-16 ***
## speed_sd 0.23301 0.03880 6.005 4.24e-09 ***
## angle_mean 0.11166 0.03429 3.257 0.00122 **
## angle_sd 0.18818 0.03560 5.286 2.04e-07 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.6731 on 408 degrees of freedom
## (52 observations deleted due to missingness)
## Multiple R-squared: 0.5514, Adjusted R-squared: 0.547
## F-statistic: 125.3 on 4 and 408 DF, p-value: < 2.2e-16
##
## Call:
## lm(formula = line_drive ~ speed_mean + angle_mean, data = fit_data2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.39294 -0.48204 -0.00955 0.45437 2.33375
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.02569 0.03675 -0.699 0.484857
## speed_mean 0.63002 0.03719 16.942 < 2e-16 ***
## angle_mean 0.14261 0.03722 3.832 0.000147 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.7461 on 410 degrees of freedom
## (52 observations deleted due to missingness)
## Multiple R-squared: 0.446, Adjusted R-squared: 0.4433
## F-statistic: 165 on 2 and 410 DF, p-value: < 2.2e-16
## df AIC
## ld_woba_multi1 6 852.0173
## ld_woba_multi2 4 935.1537
LDについても, FBと似た傾向があるようだ. 平均速度の影響が大きそうだが, 速度のSDもそれなりに効いているのかもしれない. また, 角度のSDでも正の効果があるかもしれないが, ちょっと解釈は困難である. なにかを疑似相関で拾ってきているんだと思われるがちょっとよくわからない.
PUについても無駄に計算する.
##
## Call:
## lm(formula = popup ~ speed_mean + speed_sd + angle_mean + angle_sd,
## data = fit_data2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.9955 -0.4870 -0.0978 0.4257 3.4413
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.05608 0.13115 0.428 0.6699
## speed_mean -0.17717 0.11793 -1.502 0.1364
## speed_sd 0.28575 0.12139 2.354 0.0207 *
## angle_mean 0.10811 0.12761 0.847 0.3991
## angle_sd -0.19640 0.14459 -1.358 0.1777
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.9878 on 92 degrees of freedom
## (368 observations deleted due to missingness)
## Multiple R-squared: 0.06484, Adjusted R-squared: 0.02418
## F-statistic: 1.595 on 4 and 92 DF, p-value: 0.1824
##
## Call:
## lm(formula = popup ~ speed_mean + angle_mean, data = fit_data2)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.8455 -0.6157 -0.0602 0.3783 3.3769
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.02257 0.12070 -0.187 0.852
## speed_mean -0.06843 0.10849 -0.631 0.530
## angle_mean 0.07391 0.12924 0.572 0.569
##
## Residual standard error: 1.007 on 94 degrees of freedom
## (368 observations deleted due to missingness)
## Multiple R-squared: 0.00694, Adjusted R-squared: -0.01419
## F-statistic: 0.3285 on 2 and 94 DF, p-value: 0.7209
## df AIC
## pu_woba_multi1 6 279.7663
## pu_woba_multi2 4 281.5934
どちらも全く説明できていない. 偏回帰係数の信頼区間もほぼ0に触れるものが多く, どの説明変数も有意ではなかった. そもそもほとんど個人差がないので当然だろう.
ここまでの結果からMLB15-18においては,
関連があったことが示された. では実際の価値にはどう影響があったのか? 全打球のwOBAconを同様に打球系変数で推定するモデルをつくる. 効果は直線的ではない可能性が高いため, 一般加法モデル (GAM) を用いる. 比較のため重回帰モデルの結果も示す.
# 正規化
# 説明変数からの影響の比較が容易になる
fit_data3 <- bat[, c(2:5,9)]
fit_data3 <- scale(fit_data3)
fit_data3 <- data.frame(fit_data3)
# mgcvのgamを用いる
# すべての説明変数をスプラインで入れる
wobacon_gam1 <- gam(wOBA ~ s(speed_mean) + s(speed_sd) + s(angle_mean) + s(angle_sd), data = fit_data3)
wobacon_gam2<- gam(wOBA ~ s(speed_mean) + s(angle_mean),
data = fit_data3)
summary(wobacon_gam1)
##
## Family: gaussian
## Link function: identity
##
## Formula:
## wOBA ~ s(speed_mean) + s(speed_sd) + s(angle_mean) + s(angle_sd)
##
## Parametric coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.273e-12 2.637e-02 0 1
##
## Approximate significance of smooth terms:
## edf Ref.df F p-value
## s(speed_mean) 3.841 4.835 75.28 < 2e-16 ***
## s(speed_sd) 1.000 1.000 181.76 < 2e-16 ***
## s(angle_mean) 1.603 2.012 28.26 2.28e-12 ***
## s(angle_sd) 1.000 1.000 66.78 2.40e-15 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## R-sq.(adj) = 0.677 Deviance explained = 68.2%
## GCV = 0.32926 Scale est. = 0.32328 n = 465
summary(wobacon_gam2)
##
## Family: gaussian
## Link function: identity
##
## Formula:
## wOBA ~ s(speed_mean) + s(angle_mean)
##
## Parametric coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -2.059e-17 3.147e-02 0 1
##
## Approximate significance of smooth terms:
## edf Ref.df F p-value
## s(speed_mean) 3.459 4.379 110.77 < 2e-16 ***
## s(angle_mean) 1.807 2.293 10.33 2.2e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## R-sq.(adj) = 0.539 Deviance explained = 54.5%
## GCV = 0.46683 Scale est. = 0.46054 n = 465
AIC(wobacon_gam1, wobacon_gam2)
## df AIC
## wobacon_gam1 9.443720 804.8811
## wobacon_gam2 7.265479 967.2987
# gam.check(wobacon_gam1)
# wobacon_gam3 <- gam(wOBA ~ s(speed_mean, angle_mean) + s(speed_sd) + s(angle_sd), data = fit_data3)
# summary(wobacon_gam3) #
調整済みR^2はモデル1で0.677, モデル2では0.539となり, AICでもモデル1で改善が見られる. 速度や角度の平均だけでなく, 分布の幅を考慮することの重要性を示唆していると言えるだろう.
各説明変数が変動した時の, 目的変数への影響をプロットする.
par(mfrow=c(2, 2))
plot(wobacon_gam1, se = TRUE, xlim = c(-3, 3))
x軸が各説明変数で, y軸がその説明変数の変化が及ぼす目的変数の変化を示す (単位はSD).平均速度では効果は線形からの乖離が見られるが, 他の変数ではGAMでも推定された効果としてはほぼ線形となった. 平均速度に関しては, 極端に打球速度が低い打者は, 多少速度が変化してもあまり価値が変化しないという結果で, 予想通りというところではないか. 一方, 平均角度は冒頭の図を考えるとやや意外な結果かもしれない. 可能性としては,
ほとんどの打者は角度を上げすぎて打球価値を損ねるほどには, 平均角度を高くしていない. そのため, ネガティブな効果が検出されなかった
他の変数が一定である, という条件が影響しているかもしれない? つまり, 打球角度だけに関して示した冒頭の図で高角度領域で価値が下がるのは, 打球速度の低下も含まれているはず. 打者ごとにまとめた数字と, 打球別の数字の比較なのでよくわからないが
単純にモデルの立て方が悪い
あたりがあるのではないか.
傾きを大まかに見る限り, 基本的には速度の平均値やSDの影響が大きかったようだ.
参考のため, 平均値だけのモデル2に関しても同様に示す.
par(mfrow=c(1,2))
plot(wobacon_gam2, se = TRUE)
こちらでは平均角度が少しだけより曲線的になっており, 角度をかなり上げること (全体の1SD以上の数値) は価値を高める効果があったと推定されているように見えなくもない.
線形回帰の場合の結果も示す.
wobacon_multi1 <- lm(wOBA ~ speed_mean + speed_sd + angle_mean + angle_sd,
data = fit_data3)
wobacon_multi2<- lm(wOBA ~ speed_mean + angle_mean,
data = fit_data3)
summary(wobacon_multi1)
##
## Call:
## lm(formula = wOBA ~ speed_mean + speed_sd + angle_mean + angle_sd,
## data = fit_data3)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.50665 -0.39256 -0.00263 0.34649 2.09516
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.861e-16 2.681e-02 0.000 1
## speed_mean 5.397e-01 2.939e-02 18.364 < 2e-16 ***
## speed_sd 4.042e-01 3.034e-02 13.323 < 2e-16 ***
## angle_mean 1.952e-01 2.771e-02 7.043 6.91e-12 ***
## angle_sd -2.304e-01 2.888e-02 -7.977 1.20e-14 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.5782 on 460 degrees of freedom
## Multiple R-squared: 0.6685, Adjusted R-squared: 0.6657
## F-statistic: 232 on 4 and 460 DF, p-value: < 2.2e-16
summary(wobacon_multi2)
##
## Call:
## lm(formula = wOBA ~ speed_mean + angle_mean, data = fit_data3)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.64532 -0.49703 -0.01775 0.42687 1.94530
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1.710e-17 3.186e-02 0.000 1
## speed_mean 6.948e-01 3.222e-02 21.561 < 2e-16 ***
## angle_mean 1.401e-01 3.222e-02 4.349 1.68e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.6871 on 462 degrees of freedom
## Multiple R-squared: 0.53, Adjusted R-squared: 0.5279
## F-statistic: 260.4 on 2 and 462 DF, p-value: < 2.2e-16
AIC(wobacon_multi1, wobacon_multi2)
## df AIC
## wobacon_multi1 6 817.1273
## wobacon_multi2 4 975.5704
# ANOVAでRSSチェック
# anova(wobacon_multi1, wobacon_multi2)
ここでもSDを説明変数に含めたモデル1では, 調整済みR^2は0.666, モデル2では0.528となり, モデル1で改善が見られる.
平滑化を行ったGAMと, 線形モデル (lm) である重回帰でR^2はそれほど変わらなかったようだ. これはそもそもGAMのモデルでも速度平均以外はほぼ線形であることと一致しているだろう. 確認のためSDを含めたモデルについて, R^2と関連がある残差の平方和を計算する.
fit_data3 %>%
mutate(gam_pred = predict(wobacon_gam1, fit_data3),
lm_pred = predict(wobacon_multi1, fit_data3),
gam_diff = gam_pred - wOBA,
lm_diff = lm_pred - wOBA,
wOBA_mean = mean(wOBA))%>%
dplyr::summarise(`GAMの残差平方和` = sum(gam_diff ^ 2),
`lmの残差平方和` = sum(lm_diff ^ 2),
# ついでに調整されていないR^2を計算
# R^2 = SS[regress]/SS[total] = 1 - SS[error]/SS[total]
SS_total = sum((wOBA - wOBA_mean)^2))%>%
mutate(`R^2_GAM` = 1 - `GAMの残差平方和` / SS_total, # not adjusted
`R^2_lm` = 1 - `lmの残差平方和` / SS_total)%>% # not adjusted
mutate_if(is.numeric, funs(round), 3)%>%
kable()
GAMの残差平方和 | lmの残差平方和 | SS_total | R^2_GAM | R^2_lm |
---|---|---|---|---|
147.595 | 153.794 | 464 | 0.682 | 0.669 |
残差平方和はGAMで少しだけ減少していることが確認できる.
4変数を考慮した重回帰モデル1のQQプロットを示す.
# QQ plot
ggplot(wobacon_multi1,
aes(sample = .stdresid)) +
stat_qq() +
geom_abline() +
theme_classic(base_family = "HiraKakuPro-W3")+
labs(title = "QQ plot: 重回帰モデル1")
当てはまりはそれほど悪くなさそうだ. とはいえ, 端ではある程度乖離がある.
偏回帰係数をプロット.
この偏回帰係数にどの程度の意味があるかは判断が難しいように思える. 説明変数の効果は少なくとも打球速度に関しては直線的では無さそうであるが, 平滑化を許容したGAMと線形モデルの間で当てはまりにそれほど大きな変化が無かった. これは重回帰の偏回帰係数が多少は参考になることを支持しているかもしれない.
また, 偏回帰係数の推定が不正確になる要因として, 考慮されていない要因との相関の問題がある. ここでは通算のwOBAconを打球系変数で説明することを試みたが, このような方法は説明変数と, 目的変数に影響を持つが考慮されていない要因の間に相関があると, 交絡によって偏回帰係数が直接的な影響の大きさから乖離しがちである. 一応, もう少しましかと思われるモデルもつくってみたが, 偏回帰係数の相対的な大きさはあまりかわらないことは確認した (下の, 年度間変化量を用いたwOBAcon重回帰モデルを参照).
仮に偏回帰係数がある程度信頼できるとして, 絶対値の大きさに注目すると, おそらく速度の平均とSDの影響が大きく, 角度は平均もSDも影響がやや小さいだろう. 角度では平均とSDが絶対値としては同程度というところ.
結果の解釈として重要な点としては説明変数間での相関の問題もある. これは中の人がこれまでに示した図とも関連がある. 説明のため一度示した説明変数間での相関を再掲する.
偏回帰係数の推定量はその変数以外の説明変数が固定化された状態で, その変数が変動したときにの影響の大きさを推定しているようなイメージだと大まかには思われる (どれだけ推定が正しいかは残念ながらあまり保証できない). しかし, この場合では説明変数間で多少相関が見られるため, 全体的な傾向としてはある変数が動くと他の変数も動いていたということになる.
さて, ここで角度の平均と他の変数の相関に注目する. この変数は,
ここで, 角度のSDは上昇はwOBAconを低下させるため, 角度を上昇させた際には角度のSDを介して効果が相殺されていた可能性が考えられる. これは角度を上げるとポップアップが増えるというようなことと関連があるかもしれない. このため, 平均速度で調整された状態で, 平均角度とwOBAconの影響を見ると, ただでさえそれほど大きくない偏回帰係数から期待されるほどにも打撃結果は改善していなかったのではないか. これは上の偏回帰係数のプロットでも確認できる (モデル1に比べてモデル2では係数が小さい).
この平均角度と角度のSDの間の相関がどれくらい因果的なのかはわからないが, 仮にこのような角度を上げることで角度のSDが悪化するような効果があるのであれば, 効果が部分的にキャンセルされてしまう. この結果は別の解釈も可能であり, やや上げすぎのフライを打って悪い結果になった選手たちが, 以後角度を上げるのを選択的に避けていた可能性もあり, この場合は効果というよりバイアスと呼んだほうがいいようなものを見ていることになる. 時系列的にデータを見ていくと, このあたりについてより詳しい議論が可能になるかもしれない.
この手のバイアスは他にも色々起こっている可能性が考えられる. 例えば, 近年平均角度がどちらかというと上がっている傾向にあるようなので (FB%自体は過去のトレンドより下がっていたのが回復した程度だが), 最近MLBでデビューした経験が浅い選手たちほど高い平均角度を持っている可能性があり, これは平均角度の効果を押し下げているかもしれない.
また, 平均角度は効果の直線性が疑わしい変数だと思われ, この線形モデルでは過小評価されている可能性もある (ただし, 平均角度が低い打者が角度を上げた場合, 全体より悪い結果になっていたようだ. 下の「平均角度10°以下の選手に限った重回帰モデル」参照).
一方, 速度の平均についてみると,
SDを考慮に入れてない状態で平均角度を調整した状態で見ると, 速度のSDの効果が相関を介して含められる. もともと偏回帰係数が大きく, さらに速度のSDの効果も加わった大きい影響が検出されていたとも言えるかもしれない. しかし, どうしても当たり損ねの弱い打球があるということを考えると, 平均を上げるような早い打球が増えたらSDが多少増えるのは自然で完全な分離は困難なのかもしれない. とはいえ, 同じSDで打球が速いこともあるわけで, 2変数を別々に考えることで打者の能力をより正確に捉えられる利点はあると考えられる.
というわけで, 打球の速度や角度の広がりの代表値としてSDを考慮することで, 単に平均値に注目する場合に比べて, 打球タイプやその価値, あるいはwOBAconの推定が改善する. 速度や角度の分布の幅はおそらく平均角度よりもむしろ重要であるかもしれない. ただし, これでも十分に速度や角度の分布の情報を取り入れられているかは明らかではない. より詳細に分布の情報を取り入れることでさらに打撃結果の理解が深まる可能性があるかもしれない (一応, 歪度 skewness について検討したが, 簡単な方法で見る限り影響はかなり小さいようだったので本稿では省略する. 平均速度と平均角度の相互作用項も検討したが, やはり影響は軽微だった).
イントロで述べた本稿の目的は, SDなどの分布の広がりを表現しうる変数を導入することで意味のある情報が拾えるらしいことを示すことであり, ここまでで基本的には終えている. が, もうちょっとだけ続くんじゃよ, ということでついでにGAMモデルから具体的にwOBAconの推定値を得て, その値とwOBAconなどとの関係を検討する.
# 正規化していないモデル
wOBAcon_gam <- gam(wOBA ~
s(speed_mean) + s(speed_sd) + s(angle_mean) + s(angle_sd),
data = bat)
# 打撃成績に予測値を入れる
bat$gam_wOBAcon <- predict(wOBAcon_gam)
bat <- bat %>%
mutate(wOBAcon_diff = wOBA - gam_wOBAcon,
xwOBAcon_diff = xwOBA - gam_wOBAcon)
GAMによる予測値はとりあえずgam_wOBAconとでも名付けておく. せっかくなのでTROUTについても計算し, wOBAcon, xwOBAconとの相関を調べる.
bat <- bat %>%
mutate(TROUT = speed_mean * speed_sd / angle_sd)
cor(bat %>% dplyr::select(wOBA, xwOBA, gam_wOBAcon, TROUT),
use = "pairwise.complete.obs")
## wOBA xwOBA gam_wOBAcon TROUT
## wOBA 1.0000000 0.8754729 0.8257825 0.6559721
## xwOBA 0.8754729 1.0000000 0.9287028 0.7309427
## gam_wOBAcon 0.8257825 0.9287028 1.0000000 0.7940074
## TROUT 0.6559721 0.7309427 0.7940074 1.0000000
gam_wOBAconはwOBAconやxwOBAconと比較的高い相関を示す (wOBA, xwOBAとなっているがここでは打球だけに絞って計算しているので, 正確にはwOBAconとxwOBAcon). TROUTはwOBAなどとは相関が低いが, これはそもそもTROUTがwOBAの予測を目的とするというより, あくまで注目している変数について議論し, そのおまけとして重み付けを放棄した適当な指標を作ったという部分があるだろう. 同じような説明変数に着目しているgam_wOBAconとTROUTは比較的相関が強い.
gam_wOBAconはxwOBAconと特に高い相関を示す. xwOBAconは各打球についてのそれぞれの速度と角度を利用している指標であり, 分布の代表値 (平均+SD) だけを利用しているGAMモデルでこれだけ当てはまるのは, これらの4変数でそれなりに打球の性質を反映できているといえるかもしれない. 当然, “だったらはじめからxwOBAを使えばいいのでは?” というのはまっとうな意見だと思われるが, 代表値を見ることで捉えやすくなる部分もあり必ずしも無駄では無いだろう.
wOBAconとgam_wOBAconの間の関係を可視化する.
色はwOBAcon - gam_wOBAconを示し, マゼンタが濃いほどgam_wOBAconで過小評価されている.
下はwOBAconとTROUTの間の関係と, gam_wOBAconと実際のwOBAconとの間の差を示している.
gam_wOBAconにおいて過小評価された選手はTROUTにおいても過小評価されていることがわかる.
このgam_wOBAconとTROUTは分布の広がりを考慮する変数を含めたモデルなわけだが, このような考え方が新しいとは言い難いかもしれない. 実のところ, 明示的ではないにせよこのような分布の形状がある程度評価されている指標は既に存在する. 既に言及している選手ごとにまとめたxwOBAとBarrel rate (ここではBrls/BBEをBarrel rateと呼ぶことにする)である.
まずxwOBA (ここでは打球だけを考えているのでxwOBAconを考える) との関係を検討する. xwOBAは各打球について速度と角度から打球価値を推定しているため, xwOBAの高い選手は冒頭に挙げたような好ましい分布を持っている可能性がある.
gam_wOBAconで過小評価された選手はxwOBAconでも過小評価されている.
xwOBAconを重回帰において打球変数で説明して, その偏回帰係数を確認する (モデル1).
##
## Call:
## lm(formula = xwOBA ~ speed_mean + speed_sd + angle_mean + angle_sd,
## data = fit_data4)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.12457 -0.23084 -0.02366 0.21759 1.14318
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 7.267e-16 1.645e-02 0.00 1
## speed_mean 6.606e-01 1.802e-02 36.65 <2e-16 ***
## speed_sd 3.462e-01 1.861e-02 18.61 <2e-16 ***
## angle_mean 2.788e-01 1.700e-02 16.41 <2e-16 ***
## angle_sd -3.397e-01 1.771e-02 -19.18 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.3546 on 460 degrees of freedom
## Multiple R-squared: 0.8753, Adjusted R-squared: 0.8742
## F-statistic: 807.4 on 4 and 460 DF, p-value: < 2.2e-16
すべての変数は有意であり, その自由度調整済みR^2は0.9弱である.
wOBAconの予測モデルの偏回帰係数と比較する.
重み付けにはやや違いがあるようだが, かなり近い結果が出ている. 速度のSDだけが, wOBAcon重回帰モデルでxwOBA重回帰モデルよりも影響が小さいとなっている.
次にBarrelとの関係について検討する.
Barrel zoneの大まかな形状については様々な記事で目にするだろう. Barrelの定義についてはTangoがこのブログエントリのコメント欄で記述している.
where (launch_speed * 1.5 - launch_angle) >= 117
and (launch_speed + launch_angle) >= 124
and launch_angle <= 50
and launch_speed >= 98
が現在では1つ目の条件は満たされていないようだ. 多少修正があったのかもしれない.
# バレルのチェック
barrels <- df2 %>%
filter(barrel == 1)%>%
mutate(requirement1 = launch_speed * 1.5 - launch_angle,
requirement2 = launch_speed + launch_angle)
summary(barrels$requirement1)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 97.18 119.01 126.20 126.97 134.79 186.10
# launch_speed * 1.5 - launch_angle < 117の打球は結構ある
summary(barrels$requirement2)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 124.0 127.4 131.2 132.4 136.2 164.5
summary(barrels$launch_angle)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 3.325 23.485 27.846 28.676 33.239 49.996
# 角度5°以下の打球は打球速度が120 mph超え
summary(barrels$launch_speed)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 98.0 100.6 103.2 103.8 106.4 127.3
図や条件からわかるように, Barrelは速度と角度の分布の中で, 特に打球価値が高くなるような打球を拾い上げている. このような打球が多い打者というのは, 冒頭説明したような打球速度や角度の分布の特徴を持った選手である可能性が高く, 速度のSDが大きい打者や角度のSDが小さい打者とある程度一致する可能性が考えられる. Barrelはある程度明確に分布を考慮した指標といえるかもしれない.
指標間での相関を示す.
cor.table <- round(cor(bat %>% dplyr::select(wOBA, xwOBA, gam_wOBAcon, barrel_rate), # matrixを入れる
use = "pairwise.complete.obs"), digits = 3)
corrplot(cor.table, method = "color",
addCoef.col="grey2", order = "AOE")
Barrel rateはgam_wOBAconとも高い相関を示す.
gam_wOBAconで過小評価された選手はBarrel rateでも過小評価されている. ある程度共通した情報を利用している可能性が高いだろう.
下はHR/BBEを含めて指標間での相関を示す.
woba.cor.table <- round(cor(bat[, c(9,10,12, 18, 19, 22)], # matrixを入れる
use = "pairwise.complete.obs"), digits = 3)
corrplot(woba.cor.table, method = "color",
addCoef.col="grey2", order = "AOE")
Barrel rateはTROUTとは比較的低い相関を示し, HR/BBEとは非常に高い相関を示す. そういう意味では, やはりgam_wOBAconとは多少違いがあるようだが, 基本的には似た性質を持っていそうである. ただし, これだけでは分布の幅の情報を使っているかどうかは定かではない. 例えば, 平均角度や平均速度の情報を使っているだけでも, ある程度の類似は見られるはずである.
重回帰でBarrel rateを推定し, 各変数の偏回帰係数を調べる.
##
## Call:
## lm(formula = barrel_rate ~ speed_mean + speed_sd + angle_mean +
## angle_sd, data = fit_data4)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.18959 -0.27679 -0.01597 0.26011 1.45695
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.555e-16 1.925e-02 0.000 1
## speed_mean 5.961e-01 2.110e-02 28.256 < 2e-16 ***
## speed_sd 3.505e-01 2.178e-02 16.094 < 2e-16 ***
## angle_mean 3.947e-01 1.989e-02 19.843 < 2e-16 ***
## angle_sd -1.263e-01 2.073e-02 -6.093 2.35e-09 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.415 on 460 degrees of freedom
## Multiple R-squared: 0.8292, Adjusted R-squared: 0.8277
## F-statistic: 558.4 on 4 and 460 DF, p-value: < 2.2e-16
wOBAconの予測に比べれば, 特に角度に関して顕著だが, 平均値の影響が大きいようだ. 角度のSDは低下, 速度のSDの増加はBarrel rateの上昇と相関があったようだ. 重回帰モデルと比較すると, 重み付けはやや異なるが全体的な傾向は類似している.
平均値が特に影響が大きい原因としては, 強い打球であってもBarrelにならないと全く評価されないため, ある程度ベースとなる平均角度や平均速度が無いと評価されにくい, ということがありうるだろう. このような性質を考えると, NPBのようにほとんどHRを打たない打者がそれなりにいると, Barrelによる評価はやや困難になる可能性もあるかもしれない. また, このBarrelにならないと全く評価されない性質は, 取りうる数値の極端さに繋がっている. 上のwOBAconとの散布図 (wOBAcon vs Barrel rate) を見ても分かる通り, wOBAconは0.3-0.6の範囲を取っている中でBarrel rateは0-0.3となり, 例えば比率で考えてしまうと, おかしなことになり, Barrel rateの最大の問題点となりうる. Barrel rateが0のときにwOBAconは0.3程度でそこからほぼ傾き1の直線であることから, Barrel rateは切片が0.3で傾きが1弱であると認識すると大きく間違えずにすむだろう (打球に関してだけ見た場合).
一方, Barrel rateの最大の利点は, 説明が単純であることだろう. 単によく出てくる図を示して, このへん, といえば良い. TROUTなどの明確にSDを変数として選んでいるモデルでは, 冒頭に示したような図を使うにしても少し理解のハードルが高く, このような図が手元になければ説明がさらに大変になるかもしれない. 統計にそれほど親しんでいないタイプのファンや選手たちとのコミュニケーションを考えると, この単純さはBarrel rateの大きな美徳と見るべきだろう. まずBarrel zoneを理解してもらえれば, 分布の幅の重要性の議論も伝えやすくなると思われる.
打球別の速度と角度を問題にしているxwOBAは, かなり妥当性の高い方法である (打者の走力を考慮していないので打者ごとにまとめると多少問題が大きくなるが). しかし, すべての打球についてそれぞれを価値に変換してしまう方法では, 打球の性質のうちどのようなものが影響を及ぼしているかを理解するのは困難である. Barrel rateや, 分布の代表値を利用したモデルのほうが, 解釈の容易さという点では優れているかもしれない.
注意点としてはBarrel rate自体は有用だが, Barrelは的としては大きな問題がある. 例えばBarrelの中心を狙ってしまうと, それは角度を上げすぎとなる. これは, Barrel外では高角度側はほとんど無価値になりがちのに対して, 低角度側にもそれなりに価値が高いゾーンがあるためで, 打球だけで考えてもやや低めに打つ必要がある. 現実では, 三振への影響なども考えないかもしれない.
SDに代表される分布の幅についての議論における最大の問題は, 現場においてどのように生かしうるかということかもしれない. 角度のSDを低下させることについては, 狙っている角度からずれないようにすればLDが増える, PUが減るなど, 説明自体は比較的直感的だろう. 年度間相関を見る限りでは角度のSDは個人差がはっきり存在しており, もしかしたら意図して練習することで技術的にも改善が可能かもしれない. しかし, 速度のSDを増加させるというのは, 説明すら難しい. 直感的に説明しようとすれば, 平均を気にするよりも2つ目の図の100 mph以上あたりの価値の高い打球の比率を増やすように打ってくれ, あたりになるような気がするが, そんな事言われてもどうやるんだというところかもしれない.
それでも, 基礎的な統計に馴染んでいる側からするとSDを用いることで, 打球の価値について理解しやすい部分が増える利点があるのではないだろうか. 少なくとも中の人は, このあたりを調べることでBarrelのありがたみを理解できたような気がしている.
速度と角度の分布について, 平均だけでみるよりも広がりを示す代表値としてSDを使うことで, wOBAconの推定は正確になった. 分布の広がりを考慮する重要性を示唆していると言えるだろう. 打球タイプの分類を利用してその効果を整理すると, 速度のSDが大きくなるとFBやLDの価値を高め, 角度のSDが小さくなるとLDが増加しPUが低下する. これらの効果によってwOBAconが改善したと考えられる.
1変数の単純線形回帰でみられる平均角度の効果の低さの原因としては, 角度のSDなどの他の変数での価値の毀損との関連も疑われる. このあたりの関係性の強さがどれくらいなのかはわからない.
少なくともMLBでは既存の指標としてはxwOBAやBarrel rateを使うことで, 既にある程度分布の幅を取り入れた形で選手の評価が可能になっていると言えるかもしれない.
Tango, Solution to calculation of “average” exit velocity?, 2016.
Eli Ben-Porat, Mike Trout, Statcast Darling, 2018
馬場真哉, 平滑化スプラインと加法モデル, 2017.
Phil Birnbaum, Don’t use regression to calculate Linear Weights, 2009.
Fangraphs, League stats (Batting/Batted Ball)
@sleep_in_nmbrs, xwOBAの中身拝見, 2017.
baseballsavant, Statcast Leaderboard
MLB, Barrel
Mike Petriello, Barreled up: New Statcast metric shows highest-value batted balls, 2016.
Tango, Statcast Lab: Barrels. 2016.
Tango, Does an increase in launch angle lead to an increase in strikeouts?, 2018.
上の重回帰モデルは, 各選手のwOBAconをそれぞれの通算の打球関連変数で説明させている. 影響が大きい変数を考慮に入れ損なっている場合, このような方法において推定された偏回帰係数は, 誤差項との相関によって直接的な影響の大きさから乖離している可能性がある.
そこでwOBAcon自体では無く, 年度ごとのwOBAconの変化を考える. 具体的には, 200BBE以上の連続した2年間での2年目のwOBAconを, 前年のwOBAconに加えて, 打球関連変数の年度間変化で説明することを試みる. やや複雑になるが, このような方法であれば, 考慮に入れ損なった変数からの影響が小さくなると期待される.
bat2 <- typeX %>%
group_by(player_name, game_year)%>%
dplyr::summarise(speed_mean = mean(launch_speed, na.rm = TRUE),
speed_sd = sd(launch_speed, na.rm = TRUE),
angle_mean = mean(launch_angle, na.rm = TRUE),
angle_sd = sd(launch_angle, na.rm = TRUE),
wOBA_value = sum(woba_value, na.rm = TRUE),
xwOBA_value = sum(xWOBA_value, na.rm = TRUE),
wOBA_denom = sum(woba_denom, na.rm = TRUE),
wOBA = wOBA_value / wOBA_denom,
xwOBA = xwOBA_value / wOBA_denom)%>%
filter(wOBA_denom >= 200) # 打球数
# 年度間で比較可能に組み直す
years <- c(2015, 2016, 2017)
bat.xy <- NULL
for (i in years) {
bat.x <- bat2 %>%
filter(game_year == i)
bat.y <- bat2 %>%
filter(game_year == i+1)
temp <- inner_join(bat.x, bat.y, by = "player_name")
bat.xy <- rbind(bat.xy, temp)
}
bat.xy <- bat.xy%>%
mutate(wOBA_diff = wOBA.y - wOBA.x,
speed_mean_diff = speed_mean.y - speed_mean.x,
speed_sd_diff = speed_sd.y - speed_sd.x,
angle_mean_diff = angle_mean.y - angle_mean.x,
angle_sd_diff = angle_sd.y - angle_sd.x)
# 正規化
fit_data4 <- bat.xy%>%
ungroup()%>%
dplyr::select(wOBA.x, wOBA.y, wOBA_diff, speed_mean_diff, angle_mean_diff, speed_sd_diff, angle_sd_diff)
fit_data4 <- scale(fit_data4)
fit_data4 <- data.frame(fit_data4)
diff_multi1 <- lm(wOBA.y ~ wOBA.x + speed_mean_diff + speed_sd_diff + angle_mean_diff + angle_sd_diff,
data = fit_data4)
diff_multi2 <- lm(wOBA.y ~ wOBA.x + speed_mean_diff + angle_mean_diff,
data = fit_data4)
summary(diff_multi1)
##
## Call:
## lm(formula = wOBA.y ~ wOBA.x + speed_mean_diff + speed_sd_diff +
## angle_mean_diff + angle_sd_diff, data = fit_data4)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.44245 -0.49894 -0.00287 0.44204 2.27430
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 6.551e-16 2.822e-02 0.000 1
## wOBA.x 6.779e-01 2.963e-02 22.877 < 2e-16 ***
## speed_mean_diff 3.699e-01 3.767e-02 9.819 < 2e-16 ***
## speed_sd_diff 4.333e-01 3.590e-02 12.069 < 2e-16 ***
## angle_mean_diff 1.406e-01 2.929e-02 4.800 1.99e-06 ***
## angle_sd_diff -2.214e-01 3.036e-02 -7.295 9.10e-13 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.7094 on 626 degrees of freedom
## Multiple R-squared: 0.5007, Adjusted R-squared: 0.4967
## F-statistic: 125.5 on 5 and 626 DF, p-value: < 2.2e-16
summary(diff_multi2)
##
## Call:
## lm(formula = wOBA.y ~ wOBA.x + speed_mean_diff + angle_mean_diff,
## data = fit_data4)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.7083 -0.5498 -0.0018 0.5301 2.6991
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 7.018e-16 3.235e-02 0.000 1.000
## wOBA.x 5.896e-01 3.316e-02 17.783 < 2e-16 ***
## speed_mean_diff 1.816e-01 3.299e-02 5.506 5.37e-08 ***
## angle_mean_diff 7.912e-02 3.306e-02 2.393 0.017 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.8133 on 628 degrees of freedom
## Multiple R-squared: 0.3417, Adjusted R-squared: 0.3386
## F-statistic: 108.7 on 3 and 628 DF, p-value: < 2.2e-16
AIC(diff_multi1, diff_multi2)
## df AIC
## diff_multi1 7 1367.601
## diff_multi2 5 1538.275
multiplot(diff_multi1, diff_multi2) +
theme_classic(base_family = "HiraKakuPro-W3")+
labs(title = "wOBAconの重回帰モデル2",
subtitle = "x+1年度のwOBAconを, x年度wOBAconと打球変数
の変化で説明.
バントを除いた打球の全打球速度, 角度を使用.
説明変数は正規化済み.")
このような方法でも, SDを考慮に加えたほうが推定は改善している. 前年度wOBAcon (wOBA.x) をベースラインとして説明変数に加えたため, これの影響が大きい.
打球系変数の影響の大きさの中での相対的な影響は, 打球系変数に単純にwOBAconを入れた場合と, あまり変わらなかったようだ. 大きな違いとしては, 変数の差分で説明させたモデルでは, 速度のSDの効果がやや相対的に上昇している. 基本的には速度の平均値や, SDの影響が大きい.
この方法でも平均角度の影響はSDを考慮したモデルでわずかに大きいらしい. 平均角度の上昇がSD系の変数を介して成績の悪化に繋がっていた可能性を示唆している. これは以前ブログで示した内容と整合的かもしれない. また, 平均速度もSD系の変数を加えることで影響が大きく推定されている. これも説明変数間の相関の影響だろう.
説明変数間の相関を示す.
平均角度変化は, 速度と角度のSDの悪化と極めて弱い相関があったようだ.
速度平均変化は速度SD変化と負の相関があったようだ. これは各選手の速度の平均値やSDの大きさ自体を見た場合と逆の結果である. 多くの場合, 打球速度の増加は, 速度の遅い打球の減少させることで起こっていたのかもしれない. また, 速度平均変化は角度SD変化とも負の相関を示す. これは上がりすぎた打球が速度が小さいことと関連があったのかもしれない.
実際にはこの方法でもどれだけ正確に偏回帰係数を推定できているかはあやしいかもしれない. 例えば, 前年初めに角度高めの打球が偶然悪い結果になったため全体的に角度を下げるように判断した選手が, 次の年に角度を戻した場合, 角度を上げる効果を過剰に見積もる可能性がある. 報道に反応して角度を上げた選手に何らかの特徴があった場合, それもバイアスに繋がっているかもしれない.
比較のため, 変数自体で説明させたモデルの偏回帰係数を再掲しておく.
打球角度とwOBAconの値の関係を見ると, 低角度から見ると価値が上がった後に低下する. このため, 線形モデルでは角度の効果が相殺される可能性がある.
雑な方法だが, 角度の価値が上昇していく部分に平均角度を持つ打者だけでモデルをつくってみる (angle_mean <= 10) .
打球タイプに関しては, LD%の推定が改善しそうな気がしたので確認.
##
## Call:
## lm(formula = LD_BBE ~ speed_mean + speed_sd + angle_mean + angle_sd,
## data = fit.data.low.angle)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.11971 -0.47483 0.00032 0.46457 2.99453
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -9.006e-16 5.974e-02 0.000 1.000
## speed_mean -1.311e-02 6.697e-02 -0.196 0.845
## speed_sd -6.787e-02 6.958e-02 -0.976 0.331
## angle_mean 2.855e-01 6.141e-02 4.649 7.4e-06 ***
## angle_sd -6.618e-01 6.551e-02 -10.102 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.7341 on 146 degrees of freedom
## Multiple R-squared: 0.4754, Adjusted R-squared: 0.4611
## F-statistic: 33.08 on 4 and 146 DF, p-value: < 2.2e-16
##
## Call:
## lm(formula = LD_BBE ~ speed_mean + angle_mean, data = fit.data.low.angle)
##
## Residuals:
## Min 1Q Median 3Q Max
## -2.7118 -0.6584 0.0986 0.6151 3.9081
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -8.183e-16 8.091e-02 0.000 1.000
## speed_mean 1.736e-02 8.132e-02 0.213 0.831
## angle_mean 1.548e-01 8.132e-02 1.903 0.059 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.9943 on 148 degrees of freedom
## Multiple R-squared: 0.02456, Adjusted R-squared: 0.01138
## F-statistic: 1.863 on 2 and 148 DF, p-value: 0.1588
## df AIC
## ld_multi1.low 6 342.0892
## ld_multi2.low 4 431.7612
平均角度の偏回帰係数が全体のデータで推定された0.457であり, このデータセットでは0.461となった. ほとんど変わらない.
wOBAcon.
##
## Call:
## lm(formula = wOBA ~ speed_mean + speed_sd + angle_mean + angle_sd,
## data = fit.data.low.angle)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.65500 -0.39320 0.05903 0.31863 1.55540
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1.566e-15 4.944e-02 0.000 1.000
## speed_mean 5.305e-01 5.542e-02 9.573 < 2e-16 ***
## speed_sd 4.027e-01 5.758e-02 6.995 8.87e-11 ***
## angle_mean 4.166e-02 5.082e-02 0.820 0.414
## angle_sd -2.632e-01 5.421e-02 -4.855 3.06e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.6075 on 146 degrees of freedom
## Multiple R-squared: 0.6408, Adjusted R-squared: 0.6309
## F-statistic: 65.11 on 4 and 146 DF, p-value: < 2.2e-16
##
## Call:
## lm(formula = wOBA ~ speed_mean + angle_mean, data = fit.data.low.angle)
##
## Residuals:
## Min 1Q Median 3Q Max
## -1.49860 -0.46738 0.04244 0.44071 2.11640
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1.736e-15 5.768e-02 0.000 1.000
## speed_mean 7.107e-01 5.797e-02 12.259 <2e-16 ***
## angle_mean -9.789e-03 5.797e-02 -0.169 0.866
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.7088 on 148 degrees of freedom
## Multiple R-squared: 0.5043, Adjusted R-squared: 0.4976
## F-statistic: 75.29 on 2 and 148 DF, p-value: < 2.2e-16
## df AIC
## wobacon_multi1.low 6 284.9187
## wobacon_multi2.low 4 329.5411
この集団に限っても打球角度の偏回帰係数は他の変数に比べてかなり小さい.
平均速度と平均角度だけを考慮したモデル2では, 角度を上げるとwOBAが低下している. SD系の変数の相関を拾っているためだろう. 後ほど確認する.
全体の結果とも比較しておく.
主な違いは平均角度で見られ, 打球角度が低い打者では角度を上げる効果が小さかった可能性が考えられる.
説明変数間での相関を示す.
閾値を設定するという不自然な処理を行ったため分布が汚い.
平均角度は,
後者は打球価値を損ねる影響があったはずである. 平均角度自体の効果が低かったことと合わせて, 平均だけを考慮したモデルでは, 打球角度を上げることはむしろマイナスとなったようだ.
このデータセットで平均角度を上げることの効果が悪化に繋がった可能性としては,
あたりがあるかもしれない.
# summary(typeX$launch_angle)
Group <- seq(-90, 90, 2.5)
typeX$angle_bin <- with(typeX, cut(launch_angle, Group))
angle <- typeX %>%
group_by(angle_bin)%>%
dplyr::summarise(N = n(),
mean_velo = mean(launch_speed, na.rm = TRUE),
dist = mean(hit_distance_sc, na.rm = TRUE),
wOBA_value = sum(woba_value, na.rm = TRUE),
xwOBA_value = sum(estimated_woba_using_speedangle, na.rm = TRUE),
wOBA_denom = sum(woba_denom, na.rm = TRUE),
wOBA = wOBA_value / wOBA_denom,
xwOBA = xwOBA_value / wOBA_denom)
value.by.angle <- typeX %>%
filter(launch_angle > -30 &launch_angle <= 50)%>%
group_by(angle_bin)%>%
dplyr::summarise(N = sum(woba_denom, na.rm = TRUE),
wOBAcon = sum(woba_value, na.rm = TRUE)/N,
xwOBAcon = sum(estimated_woba_using_speedangle, na.rm = TRUE)/N
)
angle.long <- value.by.angle %>%
mutate(N = N / 20000)%>% # 2軸にするためにピークの高さをだいたいで合わせている
gather(key = Type,
value = Value,
N, wOBAcon, xwOBAcon) # ggplot作図のためlong formatへ
p1 <- angle.long %>%
ggplot(aes(x = angle_bin,
y = Value,
group = Type,
color = Type,
linetype = Type)) +
geom_point(size = 1, alpha = 1) +
geom_line()+
theme_bw(base_family = "HiraKakuPro-W3") +
background_grid(major = "y", minor = "y",
size.major = 0.5, colour.major = "gray",
size.minor = 0.3, colour.minor = "gray")+
theme(axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10)) +
theme(axis.text.x = element_text(angle = 90, hjust = 1))+
scale_y_continuous(sec.axis = sec_axis(~.*20000, name = "N") ) + # 2軸目の設定
labs(title = "角度グループごとの打球の価値 (-30°~45°).",
subtitle = "色は打球タイプを示す. MLB15-18.",
x = "角度グループ", y = "wOBAcon value",
caption = "Source: Statcast."
)
# ggsave(file = "value_and_N_by_angle.png", plot = p1,
# dpi = 150,width = 8, height = 5)
# 速度のbinごとの打球価値
# summary(typeX$launch_speed)
Group2 <- seq(-0, 130, 2.5)
typeX$speed_bin <- with(typeX, cut(launch_speed, Group2))
speed <- dplyr::summarise(group_by(typeX, speed_bin),
mean_angle = mean(launch_speed, na.rm = TRUE),
dist = mean(hit_distance_sc, na.rm = TRUE),
wOBA_value = sum(woba_value, na.rm = TRUE),
xwOBA_value = sum(estimated_woba_using_speedangle, na.rm = TRUE),
wOBA_denom = sum(woba_denom, na.rm = TRUE),
wOBA = wOBA_value / wOBA_denom,
xwOBA = xwOBA_value / wOBA_denom)
value.by.speed <- typeX %>%
filter(type == "X" & launch_speed > 0 &launch_speed <= 130)%>%
group_by(speed_bin)%>%
dplyr::summarise(N = n(),
wOBAcon = sum(woba_value, na.rm = TRUE)/N,
xwOBAcon = sum(estimated_woba_using_speedangle, na.rm = TRUE)/N)%>%
filter(N >= 50)
# 作図のために組み直す
speed.long <- value.by.speed %>%
mutate(N = N / 20000)%>%
gather(key = Type,
value = Value,
N, wOBAcon, xwOBAcon)
p2 <- speed.long %>%
ggplot(aes(x = speed_bin,
y = Value,
group = Type,
color = Type,
linetype = Type)) +
geom_point(size = 1, alpha = 1) +
geom_line()+
theme_bw(base_family = "HiraKakuPro-W3") +
background_grid(major = "y", minor = "y",
size.major = 0.5, colour.major = "gray",
size.minor = 0.3, colour.minor = "gray")+
theme(axis.text.x = element_text(size=10),
axis.text.y = element_text(size=10)) +
theme(axis.text.x = element_text(angle = 90, hjust = 1))+
scale_y_continuous(sec.axis = sec_axis(~.*20000, name = "N") ) + # 2軸目の設定
labs(title = "速度グループごとの打球の価値.",
subtitle = "色は打球タイプを示す. MLB15-18.",
x = "速度グループ", y = "wOBAcon value"
,caption = "Source: Statcast.")
# ggsave(file = "value_and_N_by_speed.png", plot = p2,
# dpi = 150,width = 8, height = 5)