はじめに
今回はメジャー挑戦1年目でワールドシリーズ優勝に貢献したドジャースの山本由伸投手の投球内容を分析します。シーズン中には怪我での離脱がありましたが、最終的にはレギュラーシーズン18試合、ポストシーズン4試合に先発してワールドシリーズ制覇に貢献したシーズンでした。今回はその22試合で投げた全1751球を対象として、全投球の傾向や怪我の前後での変化などを分析します。
投球データの分析
全投球データの取得と可視化
まずはpybaseballをインストールして、山本投手のレギュラーシーズンとポストシーズンの投球データを取得します。
# pybaseballのインストール
!pip install pybaseball
import pybaseball as pb
# 山本投手のデータを取得
yamamoto_data = pb.playerid_lookup('Yamamoto', 'Yoshinobu')
# 投球のデータを取得
player_id = yamamoto_data.iloc[0, 2] # player_id = 808967
start_date = '2024-01-01'
end_date = '2024-12-31'
yamamoto_pitch = pb.statcast_pitcher(start_date, end_date, player_id)
# レギュラーシーズンとポストシーズンの投球データのみ抽出
yamamoto_pitch = yamamoto_pitch.query("game_type != 'S' and game_type != 'E'").sort_values(by=['game_date', 'inning', 'outs_when_up'])
yamamoto_pitch.head()
pitch_type game_date release_speed release_pos_x release_pos_z player_name batter pitcher events description ... n_thruorder_pitcher n_priorpa_thisgame_player_at_bat pitcher_days_since_prev_game batter_days_since_prev_game pitcher_days_until_next_game batter_days_until_next_game api_break_z_with_gravity api_break_x_arm api_break_x_batter_in arm_angle
1731 FF 2024-03-21 95.4 -1.38 5.42 Yamamoto, Yoshinobu 673490 808967 sac_fly hit_into_play ... 1 0 NaN 1.0 9.0 7.0 1.11 0.74 0.74 NaN
1732 FC 2024-03-21 89.6 -1.25 5.46 Yamamoto, Yoshinobu 673490 808967 NaN ball ... 1 0 NaN 1.0 9.0 7.0 2.08 -0.40 -0.40 NaN
1733 FF 2024-03-21 94.7 -1.24 5.60 Yamamoto, Yoshinobu 673490 808967 NaN ball ... 1 0 NaN 1.0 9.0 7.0 1.26 1.32 1.32 NaN
1734 FF 2024-03-21 96.1 -1.27 5.40 Yamamoto, Yoshinobu 673490 808967 NaN called_strike ... 1 0 NaN 1.0 9.0 7.0 1.12 0.59 0.59 NaN
1735 CU 2024-03-21 79.3 -1.04 5.63 Yamamoto, Yoshinobu 673490 808967 NaN ball ... 1 0 NaN 1.0 9.0 7.0 5.27 -1.17 -1.17 NaN
5 rows × 113 columns
表示されるデータ項目は以下の通りです。
今回の分析で扱う投球データは、以下のようにレギュラーシーズン(R)の1469球とポストシーズン(ディビジョンシリーズ(D)123球、リーグチャンピオンシップシリーズ(L)73球、ワールドシリーズ(W)86球)の282球の合計1751球となります。
yamamoto_pitch['game_type'].value_counts()
count
game_type
R 1469
D 123
W 86
L 73
dtype: int64
また、以下のように試合日でソートして、登板日と投球数を以下のようにまとめました。怪我で緊急降板となった試合の前の試合の106球が最大の球数で、怪我からの復帰後は最後の登板となったワールドシリーズでの86球が最大でした。
yamamoto_pitch['game_date'].value_counts().sort_index()
ここからは各投球データを可視化して、今季の全投球を分析します。まずは球種についてです。
import pandas as pd
pd.crosstab(yamamoto_pitch['pitch_name'], yamamoto_pitch['type'], margins=True)
Bがボール、Sがストライク、Xがヒットやゴロなどを含めて打者がバットに当てたときを表しています。また、割合は以下のようになります。
import pandas as pd
pd.crosstab(yamamoto_pitch['pitch_name'], yamamoto_pitch['type'], normalize='index')
フォーシームとカーブはストライク率が50%を超え、ボール率は共に30%程度となっています。スイーパーと判定されている1球を除けば、カーブはバットに当たっている割合が最も低く、ストライクを取るために特に安定して使うことができるボールであったと言えます。また、球種ごとの球速とコースを可視化すると以下のようになります。なお、コースは打者目線となっています。
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(8,4))
sns.boxplot(x='pitch_name', y='release_speed', data=yamamoto_pitch)
plt.show()
import matplotlib.pyplot as plt
import seaborn as sns
sns.scatterplot(x=yamamoto_pitch['plate_x'], y=yamamoto_pitch['plate_z'], hue=yamamoto_pitch['pitch_name'])
plt.xlim(-3, 6)
plt.ylim(-2, 6)
# ストライクゾーンを描画
x = [-0.83, 0.83, 0.83, -0.83]
y = [1.5, 1.5, 3.5, 3.5]
plt.fill(x, y, color='k', alpha=0.3)
plt.title('pitch course')
plt.show()
各球種ごとの打席結果は以下のようになっています。
import pandas as pd
pd.crosstab(yamamoto_pitch['pitch_name'], yamamoto_pitch['events'], margins=True)
events double field_error field_out fielders_choice force_out grounded_into_double_play hit_by_pitch home_run sac_bunt sac_fly single strikeout triple truncated_pa walk All
pitch_name
4-Seam Fastball 8 1 78 0 1 2 0 5 1 2 25 29 1 1 18 172
Curveball 6 1 33 1 2 1 0 2 0 0 9 26 0 0 3 84
Cutter 2 0 16 0 2 1 0 1 0 1 5 1 0 0 0 29
Sinker 2 0 6 0 0 0 1 0 0 0 2 1 0 0 0 12
Slider 1 1 7 0 0 1 0 0 0 0 2 15 0 0 2 29
Split-Finger 4 0 39 0 3 1 1 2 0 1 12 48 1 0 5 117
All 23 3 179 1 8 6 2 10 1 4 55 120 2 1 28 443
この中で、ヒット(single, double, triple, home_run)となった結果を抽出して、コースを可視化してみます。
import pandas as pd
hit = yamamoto_pitch.query('events=="single" or events=="double" or events=="triple" or events=="home_run"')
pd.crosstab(hit['pitch_name'], hit['events'], margins=True)
以下のようにコースを可視化してみると、ほとんどがストライクゾーン内のボールであるため、どの球種でも甘いボールを逃してくれないという印象を受けます。
import matplotlib.pyplot as plt
import seaborn as sns
sns.scatterplot(x=hit['plate_x'], y=hit['plate_z'], hue=hit['pitch_name'])
plt.xlim(-3, 6)
plt.ylim(-2, 6)
x = [-0.83, 0.83, 0.83, -0.83]
y = [1.5, 1.5, 3.5, 3.5]
plt.fill(x, y, color='k', alpha=0.2)
plt.title('opp hits')
plt.show()
次に、三振を奪った球種についてです。
strikeout = yamamoto_pitch.query('events=="strikeout"')
strikeout['pitch_name'].value_counts()
count
pitch_name
Split-Finger 48
4-Seam Fastball 29
Curveball 26
Slider 15
Cutter 1
Sinker 1
スプリットで多くの三振を奪っています。また、以下のように可視化してみると、ボール球となるスプリットを振らせて多くの三振を奪っていることがわかります。
import matplotlib.pyplot as plt
import seaborn as sns
sns.scatterplot(x=strikeout['plate_x'], y=strikeout['plate_z'], hue=strikeout['pitch_name'])
plt.xlim(-3, 6)
plt.ylim(-2, 6)
x = [-0.83, 0.83, 0.83, -0.83]
y = [1.5, 1.5, 3.5, 3.5]
plt.fill(x, y, color='k', alpha=0.2)
plt.title('strikeout')
plt.show()
最後にリリースポイントです。打者目線でどの位置で手からボールが離れたのか球種ごとに可視化します。
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(5,5))
sns.scatterplot(x=yamamoto_pitch['release_pos_x'], y=yamamoto_pitch['release_pos_z'], hue=yamamoto_pitch['pitch_name'])
plt.xlim(-4, 0)
plt.ylim(3, 7)
plt.title('Release point')
plt.show()
参考までに、大谷翔平投手、ダルビッシュ有投手の2021年から3シーズン分のデータを以下に示します。グラフのスケールは同じなので、山本投手のリリースポイントが球種による差が少ないことがわかります。
怪我での離脱前後の比較
次に怪我での離脱前後で投球データがどのように変化していたのか分析をします。以下のように6月15日の試合で28球投げて降板した後、3ヶ月ほど怪我のために実戦から遠ざかっていました。
# 怪我の前後でデータを分割
before = yamamoto_pitch.query('game_date < "2024-06-16"')
after = yamamoto_pitch.query('game_date > "2024-06-16"')
print(before['game_date'].value_counts().sort_index())
print(after['game_date'].value_counts().sort_index())
game_date
2024-03-21 43
2024-03-30 68
2024-04-06 80
2024-04-12 91
2024-04-19 99
2024-04-25 97
2024-05-01 94
2024-05-07 97
2024-05-13 84
2024-05-20 100
2024-05-26 100
2024-06-01 101
2024-06-07 106
2024-06-15 28
Name: count, dtype: int64
game_date
2024-09-10 59
2024-09-16 72
2024-09-22 79
2024-09-28 71
2024-10-05 60
2024-10-11 63
2024-10-17 73
2024-10-26 86
Name: count, dtype: int64
怪我の前後でヒット打たれた球種について比較します。
#怪我前のデータ
import pandas as pd
hit_before = before.query('events=="single" or events=="double" or events=="triple" or events=="home_run"')
b1 = before['pitch_name'].value_counts()
b2 = hit_before['pitch_name'].value_counts()
opp_hit_before = pd.concat([b1, b2], axis=1)
opp_hit_before.columns = ['pitch_count', 'opp_hit']
opp_hit_before['rate'] = opp_hit_before['opp_hit']/opp_hit_before['pitch_count']
opp_hit_before.sort_index()
# 怪我後のデータ
import pandas as pd
hit_after = after.query('events=="single" or events=="double" or events=="triple" or events=="home_run"')
a1 = after['pitch_name'].value_counts()
a2 = hit_after['pitch_name'].value_counts()
opp_hit_after = pd.concat([a1, a2], axis=1)
opp_hit_after.columns = ['pitch_count', 'opp_hit']
opp_hit_after['rate'] = opp_hit_after['opp_hit']/opp_hit_after['pitch_count']
opp_hit_after.sort_index()
中継の解説などで、怪我後はスライダーが良くなったというコメントを多数見かけましたが、実際には怪我の前後で投球数も打たれた数もほとんど差はありませんでした。また、各球種を比較すると、シンカーの数が極端に少なくなり、カットボールやスライダーの割合が高くなったことがわかりました。カットやスライダーといった斜めに曲がる球種を投げる割合が増加したものの、打たれた数に大きな差がなかったため、スライダーが良くなったというような印象を受けたのかもしれません。
最後にリリースポイントの変化を可視化してみます。
# 怪我の前後を示す'before_after'をデータ項目として追加
before_after = yamamoto_pitch.copy()
before_after['before_after'] = before_after['game_date'].apply(lambda x: 'before' if x < '2024-06-16' else 'after')
import matplotlib.pyplot as plt
import seaborn as sns
plt.figure(figsize=(5,5))
sns.scatterplot(x=before_after['release_pos_x'], y=before_after['release_pos_z'], hue=before_after['before_after'], alpha=0.07)
plt.xlim(-4, 0)
plt.ylim(3, 7)
plt.title('Release point (before vs after injury)')
plt.show()
怪我の後はボールを離す位置が斜め下方向に変わっていました。この傾向は以下のように各球種でも同様に確認できました。
import matplotlib.pyplot as plt
import seaborn as sns
four_seam = before_after.query('pitch_name=="4-Seam Fastball"')
plt.figure(figsize=(5,5))
sns.scatterplot(x=four_seam['release_pos_x'], y=four_seam['release_pos_z'], hue=four_seam['before_after'], alpha=0.15)
plt.xlim(-4, 0)
plt.ylim(3, 7)
plt.title('Release point (4-seam, before vs after injury)')
plt.show()
以下、コードは割愛しますが、他の球種についてもリリースポイントを可視化してみます。
各球種について、怪我の前後で同様の傾向が見られました。
分析結果の総括と所感
分析の結果、フォーシームやカーブで安定的にストライクが取れていたということや、ボール球のスプリットを振らせて多くの三振を奪っていたことがわかりました。また、怪我の前後でリリースポイントに変化が生じていることもわかりました。その変化を加味しても全体としてはリリースポイントが安定していて、打者目線では球種の判別がしにくいということになるため、山本投手の投球スタイルの1つの強みであると思います。
終わりに
今回は、昨シーズンの山本投手の投球データの分析を行いました。怪我の前後でリリースポイントに変化が生じており、これがいよいよ日本で開幕を迎える新シーズンでも継続していくのか、それとも怪我前の位置に戻っていくのか、シーズン終了後にまた比較分析を行いたいと思います。