← 記事一覧へ

「ファストボール・カウント」は, 投手が速球を投げやすいカウントのことです. 本当にそんなカウントがあるのか, あるとしたら何で決まるのかを見ます.

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ストライクで速球を減らします. 向きはほぼ共通で, 減らし方の大きさに個性が出ます.

注意

  • 2024年の1シーズンです.
  • Statcast の球種は自動分類で, とくにツーシームとシンカー, カッターと スライダーの境目は曖昧です. 分類が変われば比率も変わります.
  • カウントは打者・走者・点差と相関します. ここで見ているのは 「カウントの効果」ではなく, カウントごとの実際の配球です.
  • 敬遠球 (IN) とウエスト (PO) は配球の選択ではないので除いています.