「ファストボール・カウント」は, 投手が速球を投げやすいカウントのことです. 本当にそんなカウントがあるのか, あるとしたら何で決まるのかを見ます.
library(data.table)
library(dplyr)
library(tidyr)
library(ggplot2)
library(plotly)
library(knitr)
SEASON <- 2024
src <- sprintf("../../data/statcast_%d_all.csv", SEASON)
if (!file.exists(src)) {
stop("データがありません: ", src,
"\n Rscript data/build-statcast.R ", SEASON, " --all-pitch-types")
}
dat <- fread(src)
2024年の全投球711,776球です.
もとは2013年のpitch f/xデータで, 黒田博樹・ダルビッシュ有・カーショウの 3投手ぶんだけを持っていました. データ取得元だったMLB GameDayのXMLフィードは 停止していて取り直せないので, Baseball Savant (Statcast) に載せ替えました.
3投手から全リーグに増えたので, 「速球を投げやすいカウント」があるかどうかを リーグ全体で確かめられます.
pitches <-
dat |>
filter(!is.na(pitch_type), pitch_type != "",
!pitch_type %in% c("IN", "PO", "AB")) # 敬遠球・ウエストは配球ではない
pitches |>
count(pitch_type, sort = TRUE) |>
mutate(割合 = n / sum(n)) |>
head(12) |>
kable(digits = 3, format.args = list(big.mark = ","))
| pitch_type | n | 割合 |
|---|---|---|
| FF | 225,910 | 0.319 |
| SI | 111,897 | 0.158 |
| SL | 104,360 | 0.147 |
| CH | 72,468 | 0.102 |
| FC | 58,206 | 0.082 |
| ST | 51,983 | 0.073 |
| CU | 43,767 | 0.062 |
| FS | 21,898 | 0.031 |
| KC | 12,358 | 0.017 |
| SV | 3,695 | 0.005 |
| KN | 1,056 | 0.001 |
| FA | 631 | 0.001 |
FASTBALL <- c("FF", "FT", "SI", "FC") # 4シーム・2シーム・シンカー・カッター
pitches[, fast := pitch_type %in% FASTBALL]
シンカー (SI) を速球に含めるかで結果が変わります.
2014年当時のコードは SI を外して FS
(スプリット) を入れていました. シンカーは速球,
スプリットは変化球と数えるのが普通です.
pitches |>
summarise(`速球 (FF,FT,SI,FC)` = mean(fast),
`SI を外した場合` = mean(pitch_type %in% c("FF", "FT", "FC")),
`旧定義 (FS を含む)` = mean(pitch_type %in% c("FF", "FT", "FC", "FS"))) |>
kable(digits = 3)
| 速球 (FF,FT,SI,FC) | SI を外した場合 | 旧定義 (FS を含む) |
|---|---|---|
| 0.558 | 0.401 | 0.432 |
COUNTS <- c("0-0","0-1","0-2","1-0","1-1","1-2","2-0","2-1","2-2","3-0","3-1","3-2")
by_count <-
pitches |>
filter(balls <= 3, strikes <= 2) |>
summarise(球数 = n(), 速球比率 = mean(fast), .by = c(balls, strikes)) |>
mutate(count = factor(paste(balls, strikes, sep = "-"), levels = COUNTS),
差 = balls - strikes) |>
arrange(count)
by_count |> select(count, 球数, 速球比率) |>
kable(digits = 3, format.args = list(big.mark = ","))
| count | 球数 | 速球比率 |
|---|---|---|
| 0-0 | 182,105 | 0.610 |
| 0-1 | 92,816 | 0.510 |
| 0-2 | 48,740 | 0.445 |
| 1-0 | 68,021 | 0.595 |
| 1-1 | 71,455 | 0.512 |
| 1-2 | 70,106 | 0.449 |
| 2-0 | 22,551 | 0.708 |
| 2-1 | 36,397 | 0.590 |
| 2-2 | 59,293 | 0.493 |
| 3-0 | 6,835 | 0.947 |
| 3-1 | 14,950 | 0.779 |
| 3-2 | 35,901 | 0.631 |
by_count |>
mutate(ストライク = factor(strikes)) |>
ggplot(aes(x = balls, y = 速球比率, colour = ストライク, group = ストライク)) +
geom_hline(yintercept = mean(pitches$fast), linetype = "dashed") +
geom_line() + geom_point(aes(size = 球数)) +
scale_y_continuous(labels = scales::percent, limits = c(0, 1)) +
scale_x_continuous(breaks = 0:3) +
xlab("ボール数") +
ggtitle("追い込むほど変化球, 追い込まれるほど速球 (破線は全体平均)")

ボール数からストライク数を引いた値でほぼ説明できます (相関 0.92). 最も速球が多いのが3-0の95%, 最も少ないのが0-2の44%です.
四球を出したくないカウントではストライクを取りに速球, 追い込んだら 空振りを狙って変化球, という素直な話です.
by_count |>
ggplot(aes(x = 差, y = 速球比率)) +
geom_point(aes(size = 球数), alpha = 0.7) +
geom_smooth(method = "lm", formula = y ~ x, se = FALSE, linewidth = 0.5) +
scale_y_continuous(labels = scales::percent) +
xlab("ボール数 − ストライク数") +
ggtitle("1本の直線にほぼ乗る")

ただし差だけでは決まりません. 2つ, 外れ方があります.
1つめ. フルカウント (3-2) が浮きます.
by_count |> filter(差 == 1) |>
select(count, 球数, 速球比率) |> kable(digits = 3, format.args = list(big.mark = ","))
| count | 球数 | 速球比率 |
|---|---|---|
| 1-0 | 68,021 | 0.595 |
| 2-1 | 36,397 | 0.590 |
| 3-2 | 35,901 | 0.631 |
同じ差の 1-0 / 2-1 より高い 63% です. 1球ボールなら四球なので, 避けずに勝負するということでしょう.
2つめ. 同じ差でも, ストライクが多いほど速球が減ります.
by_count |> filter(差 == 0) |>
select(count, 球数, 速球比率) |> kable(digits = 3, format.args = list(big.mark = ","))
| count | 球数 | 速球比率 |
|---|---|---|
| 0-0 | 182,105 | 0.610 |
| 1-1 | 71,455 | 0.512 |
| 2-2 | 59,293 | 0.493 |
0-0 は 61%, 1-1 は 51%, 2-2 は 49%. 差はどれも0ですが, ストライクが増えるほど下がります. 「追い込んだかどうか」は, 差とは別に効いています.
球数の多い投手を見ます.
top_pitchers <-
pitches |>
summarise(球数 = n(), 速球比率 = mean(fast), .by = player_name) |>
filter(球数 >= 2000) |>
arrange(desc(球数))
top_pitchers |> head(10) |> kable(digits = 3, format.args = list(big.mark = ","))
| player_name | 球数 | 速球比率 |
|---|---|---|
| Webb, Logan | 3,200 | 0.478 |
| Nola, Aaron | 3,189 | 0.575 |
| Cease, Dylan | 3,188 | 0.441 |
| Wheeler, Zack | 3,134 | 0.700 |
| Ragans, Cole | 3,118 | 0.531 |
| Lugo, Seth | 3,112 | 0.513 |
| Rodón, Carlos | 3,102 | 0.529 |
| Peralta, Freddy | 3,066 | 0.539 |
| Irvin, Jake | 3,046 | 0.650 |
| Gilbert, Logan | 3,042 | 0.427 |
104人が2000球以上投げています. 速球比率は34%から 86%まで幅があります.
top_pitchers |>
ggplot(aes(x = 速球比率)) +
geom_histogram(bins = 30) +
geom_vline(xintercept = mean(pitches$fast), linetype = "dashed", colour = "firebrick") +
scale_x_continuous(labels = scales::percent) +
ylab("投手数") +
ggtitle("投手ごとの速球比率 (2000球以上, 赤破線はリーグ全体)")

fast_rate <- function(pitcher) {
d <-
pitches |>
filter(player_name == pitcher, balls <= 3, strikes <= 2) |>
summarise(速球 = mean(fast), .by = c(balls, strikes)) |>
mutate(count = factor(paste(balls, strikes, sep = "-"), levels = COUNTS),
変化球 = 1 - 速球) |>
arrange(count) |>
pivot_longer(c(速球, 変化球), names_to = "球種", values_to = "比率")
plot_ly(d, x = ~count, y = ~比率, color = ~球種, type = "bar",
colors = c(速球 = "#d95f02", 変化球 = "#7570b3")) |>
layout(barmode = "stack", title = paste0("速球比率: ", pitcher),
xaxis = list(title = "カウント", categoryorder = "array",
categoryarray = COUNTS),
yaxis = list(title = "比率", tickformat = ".0%"),
legend = list(orientation = "h"))
}
fast_rate(top_pitchers$player_name[1])
fast_rate(top_pitchers$player_name[2])
投手ごとに「2ストライクのとき速球をどれだけ減らすか」を出します.
shift <-
pitches |>
semi_join(top_pitchers, by = "player_name") |>
mutate(追い込み = strikes == 2) |>
summarise(速球比率 = mean(fast), .by = c(player_name, 追い込み)) |>
pivot_wider(names_from = 追い込み, values_from = 速球比率,
names_prefix = "s") |>
mutate(差 = sTRUE - sFALSE)
tibble::tibble(
投手数 = nrow(shift),
`減らす投手の割合` = mean(shift$差 < 0),
`差の中央値` = median(shift$差)
) |> kable(digits = 3)
| 投手数 | 減らす投手の割合 | 差の中央値 |
|---|---|---|
| 104 | 0.865 | -0.095 |
shift |>
ggplot(aes(x = 差)) +
geom_histogram(bins = 40) +
geom_vline(xintercept = 0, linetype = "dashed") +
xlab("2ストライク時の速球比率 − それ以外") +
ggtitle("ほぼ全員が同じ向きに動かす")

87%の投手が2ストライクで速球を減らします. 向きはほぼ共通で, 減らし方の大きさに個性が出ます.
IN) とウエスト (PO)
は配球の選択ではないので除いています.