1
2

MLBピッチャーのデータ分析:今永昇太選手の投球を解剖する(第3回)

Last updated at Posted at 2024-07-28

MLBピッチャーのデータ分析:今永昇太選手の投球を解剖する(第3回)

こんにちは。今回は今永昇太選手のリリース特性について詳しく分析していきます。リリース特性とは、ボールが投手の手を離れた瞬間の様々な特徴を指します。

1. リリーススピード

まず、各球種のリリーススピードを見ていきましょう。

import matplotlib.pyplot as plt
import seaborn as sns

def plot_release_speed_boxplot(df):
    # マイル表示のグラフ
    plt.figure(figsize=(12, 6))
    sns.boxplot(x='pitch_type', y='release_speed', data=df)
    plt.title('Release Speed by Pitch Type (mph)')
    plt.xlabel('Pitch Type')
    plt.ylabel('Release Speed (mph)')
    plt.show()

    # キロメートル表示のグラフ
    plt.figure(figsize=(12, 6))
    sns.boxplot(x='pitch_type', y='release_speed', data=df.assign(release_speed=df['release_speed'] * 1.60934))
    plt.title('Release Speed by Pitch Type (km/h)')
    plt.xlabel('Pitch Type')
    plt.ylabel('Release Speed (km/h)')
    plt.show()

plot_release_speed_boxplot(df_684007_all_dates)


このグラフから以下のことが分かります:

  1. 4シームファストボール(FF)が最も速く、平均約92 mph程度です。
  2. スイーパー(ST)とスプリットフィンガー(SF)は似たような速度帯で、約82-83 mph程度です。
  3. カーブ(CU)が最も遅く、約73 mph程度です。

2. スピンレート

次に、各球種のスピンレートを見てみましょう。

def plot_spin_rate_boxplot(df):
    plt.figure(figsize=(12, 6))
    sns.boxplot(x='pitch_type', y='release_spin_rate', data=df)
    plt.title('Spin Rate by Pitch Type')
    plt.xlabel('Pitch Type')
    plt.ylabel('Spin Rate (rpm)')
    plt.show()

plot_spin_rate_boxplot(df_684007_all_dates)

このグラフから以下のことが読み取れます:

  1. スイーパー(ST)のスピンレート、平均約2430 rpm程度です。
  2. 4シームファストボール(FF)のスピンレート、平均約2500 rpm程度です。
  3. スプリットフィンガー(SF)は低いスピンレートで、1150 rpm程度です。

3. リリースポイント

リリースポイントは、x(水平方向)、y(投手板からの距離)、z(垂直方向)の3つの座標で表されます。ここでは、x座標とz座標に注目してみましょう。

def plot_release_point_scatter(df):
    plt.figure(figsize=(12, 8))
    for pitch_type in df['pitch_type'].unique():
        subset = df[df['pitch_type'] == pitch_type]
        plt.scatter(subset['release_pos_x'], subset['release_pos_z'], label=pitch_type, alpha=0.5)
    plt.title('Release Point (X vs Z)')
    plt.xlabel('Release Position X (ft)')
    plt.ylabel('Release Position Z (ft)')
    plt.legend()
    plt.show()

plot_release_point_scatter(df_684007_all_dates)

分割する

import matplotlib.pyplot as plt
import numpy as np

def plot_release_points_individual_and_combined(df):
    pitch_types = df['pitch_type'].unique()
    n_pitches = len(pitch_types)
    
    # サブプロットのグリッドを設定(個別グラフ用 + 全体グラフ用)
    n_rows = (n_pitches + 1) // 2 + 1
    fig, axs = plt.subplots(n_rows, 2, figsize=(20, 6*n_rows))
    fig.suptitle('Release Points by Pitch Type', fontsize=24)
    
    # カラーマップの設定
    colors = plt.cm.rainbow(np.linspace(0, 1, n_pitches))
    
    # x軸とy軸の範囲を計算
    x_min, x_max = df['release_pos_x'].min(), df['release_pos_x'].max()
    y_min, y_max = df['release_pos_z'].min(), df['release_pos_z'].max()
    
    # 軸の範囲に少しマージンを追加
    x_margin = (x_max - x_min) * 0.1
    y_margin = (y_max - y_min) * 0.1
    x_min, x_max = x_min - x_margin, x_max + x_margin
    y_min, y_max = y_min - y_margin, y_max + y_margin
    
    # 個別グラフの作成
    for i, (pitch_type, color) in enumerate(zip(pitch_types, colors)):
        row = i // 2
        col = i % 2
        ax = axs[row, col]
        
        subset = df[df['pitch_type'] == pitch_type]
        ax.scatter(subset['release_pos_x'], subset['release_pos_z'], 
                   alpha=0.7, s=50, c=[color], label=pitch_type)
        
        ax.set_title(f'{pitch_type} Release Points', fontsize=16)
        ax.set_xlabel('Release Position X (ft)', fontsize=12)
        ax.set_ylabel('Release Position Z (ft)', fontsize=12)
        ax.grid(True, linestyle='--', alpha=0.7)
        ax.legend(fontsize=10)
        ax.set_xlim(x_min, x_max)
        ax.set_ylim(y_min, y_max)
    
    # 使用していないサブプロットを削除
    for i in range(n_pitches, n_rows * 2 - 1):
        fig.delaxes(axs.flatten()[i])
    
    # 全体グラフの作成
    ax_combined = axs[-1, -1]
    for pitch_type, color in zip(pitch_types, colors):
        subset = df[df['pitch_type'] == pitch_type]
        ax_combined.scatter(subset['release_pos_x'], subset['release_pos_z'], 
                            alpha=0.7, s=50, c=[color], label=pitch_type)
    
    ax_combined.set_title('All Pitch Types Release Points', fontsize=16)
    ax_combined.set_xlabel('Release Position X (ft)', fontsize=12)
    ax_combined.set_ylabel('Release Position Z (ft)', fontsize=12)
    ax_combined.grid(True, linestyle='--', alpha=0.7)
    ax_combined.legend(fontsize=10, bbox_to_anchor=(1.05, 1), loc='upper left')
    ax_combined.set_xlim(x_min, x_max)
    ax_combined.set_ylim(y_min, y_max)
    
    plt.tight_layout()
    plt.show()

# 関数を呼び出す
plot_release_points_individual_and_combined(df_684007_all_dates)

このグラフから以下のことが分かります:

  1. 今永選手は概ね一定のリリースポイントから投球しています。
  2. FF : x座標は約-2.5 ft付近(投手から見て左側)、z座標は約5.2-5.6 ft付近です。
  3. FS : 変化の仕方を変える、コースの狙いによって、リリースポイントが変わってる可能性がありそうです。

4. リリース特性の時系列変化

最後に、これらのリリース特性がシーズンを通じてどのように変化したかを見てみましょう。例として、4シームファストボールのリリーススピードの推移を見てみます。

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

def plot_release_speed_evolution_boxplot_with_stats(df, unit='mph'):
    ff_data = df[df['pitch_type'] == 'FF'].copy()
    ff_data['game_date'] = pd.to_datetime(ff_data['game_date'])

    if unit == 'km/h':
        ff_data['release_speed'] = ff_data['release_speed'] * 1.60934  # マイルをキロメートルに変換

    # 日付ごとの統計情報を計算
    stats = ff_data.groupby('game_date')['release_speed'].agg(['count', 'mean', 'std'])
    stats.columns = ['N', 'Average', 'σ']

    # Nは整数、AverageとσはOK小数点第一位まで丸める
    stats['N'] = stats['N'].astype(int)
    stats['Average'] = stats['Average'].round(1)
    stats['σ'] = stats['σ'].round(1)

    fig, ax = plt.subplots(figsize=(22, 14))  # 図のサイズをさらに大きくしました

    # ボックスプロットを描画
    sns.boxplot(x='game_date', y='release_speed', data=ff_data, ax=ax)
    ax.set_title(f'Four-Seam Fastball Release Speed Evolution (Daily) - {unit}', fontsize=20)
    ax.set_xlabel('Date', fontsize=18)
    ax.set_ylabel(f'Release Speed ({unit})', fontsize=18)
    ax.tick_params(axis='both', which='major', labelsize=14)  # 軸の目盛りのフォントサイズを大きく

    # X軸のティックとラベルを調整
    xticks = ax.get_xticks()
    ax.set_xticks(xticks)
    ax.set_xticklabels([])

    # 統計情報のテーブルを作成
    table_data = stats.T.values.tolist()

    table = ax.table(cellText=table_data,
                     rowLabels=stats.columns,
                     colLabels=[d.strftime('%Y-%m-%d') for d in stats.index],
                     loc='bottom',
                     cellLoc='center',
                     bbox=[0, -0.38, 1, 0.28])  # テーブルの位置とサイズを調整

    table.auto_set_font_size(False)
    table.set_fontsize(12)  # テーブルのフォントサイズをさらに大きく
    table.scale(1, 2.0)  # テーブルの高さをさらに大きく

    # テーブルの列幅を調整
    table.auto_set_column_width(col=list(range(len(stats.index) + 1)))

    # グラフの下端を調整してテーブルのスペースを確保
    plt.subplots_adjust(bottom=0.28)

    plt.tight_layout()
    plt.show()

# マイル表示のグラフを作成
plot_release_speed_evolution_boxplot_with_stats(df_684007_all_dates, 'mph')

# キロメートル表示のグラフを作成
plot_release_speed_evolution_boxplot_with_stats(df_684007_all_dates, 'km/h')

このグラフから以下のような傾向が読み取れます:
承知しました。以下に、より簡潔なまとめを提示します:

  1. 速度範囲:Four-Seam Fastballの速度は主に90-93 mph間で推移。
  2. 平均速度:全期間を通じて約91-92 mph前後で安定。
  3. ピーク:2024-06-27と2024-04-13に最高速の93.0 mph平均を記録。
  4. 最低速:2024-06-21に最低の90.1 mph平均。
  5. 変動性:日によって異なるが、多くの日で比較的安定。標準偏差は0.7-1.4の範囲。
  6. サンプル数:1日あたり29-64投の範囲で変動。
  7. 傾向:長期的な明確な上昇・下降傾向はないが、6月下旬から7月にやや速度上昇の兆候。
  8. 外れ値:数日で顕著な外れ値を観察、特に2024-04-20に極端な低速記録。

全体として、投手のFour-Seam Fastballの速度は日々の変動はあるものの、比較的一貫性がある。後半にわずかな改善が見られるが、継続的な観察が必要。

まとめ

全てのデータを総合的に分析すると、以下のようにまとめられます:

  1. 投球レパートリー:

    • Four-Seam Fastball (FF) を主軸とし、Split-Finger (FS) とスイーパー (ST) を効果的に組み合わせています。
    • 左右打者で異なる配球戦略を採用し、特に左打者に対してSTの使用頻度が高くなっています。
  2. 速度特性:

    • FF: 平均91.8 mph、日々90-93 mphの範囲で安定。
    • FS: 平均83.1 mph、FFとの速度差約8-9 mph。
    • ST: 平均81.9 mph、さらに大きな速度差。
  3. リリースポイント:

    • 各球種で微妙に異なるリリースポイントを使い分け、打者の球種識別を困難にしています。
    • FFは最も一貫したリリースポイントを持ち、これが安定した速度と制球に寄与しています。
  4. 投球の一貫性:

    • 日々のFF速度データから、全体的に安定したパフォーマンスを維持していることがわかります。
    • 各球種の速度の標準偏差が小さく、コンスタントな投球ができています。
  5. 戦略的観点:

    • リリースポイントと速度の組み合わせにより、効果的な球種の使い分けを実現しています。
    • 左右打者への異なるアプローチが、投手の適応力と戦略的思考を示しています。

総じて、この投手は優れたFFを軸に、多様な球種を巧みに組み合わせ、リリースポイントの微妙な調整と安定した速度コントロールにより、効果的な投球を行っていると評価できます。日々の微小な変動はありますが、全体として一貫した高いパフォーマンスを維持しています。


次回は、ボールの動き(ムーブメント)について詳しく分析していきます。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2