Featured image of post 【pybaseball基礎編⑥】打球単位のデータ取得

【pybaseball基礎編⑥】打球単位のデータ取得

pybaseballを使ってMLBのStatcastデータから打球だけを取り出し、打球速度、打球角度、打球距離、打球タイプなどを分析する方法をGoogle Colabの実例で解説します。

記事のシリーズ

  1. pybaseball基礎編① pybaseballのライブラリの概要とインストール
  2. pybaseball基礎編② シーズン単位のデータ取得
  3. pybaseball基礎編③ 試合単位のデータ取得
  4. pybaseball基礎編④ 打席単位のデータ取得
  5. pybaseball基礎編⑤ 1球単位のデータ取得
  6. pybaseball基礎編⑥ 打球単位のデータ取得【本記事】
  7. pybaseball基礎編⑦ 投球単位のデータ取得(予定)

はじめに

前回はStatcastの1球単位のデータを取り上げ、球種、球速、カウント、description などを確認しました。

今回はそこから一歩進み、バットに当たって打球になったデータだけを取り出す方法を解説します。

Statcastでは、投球データの中に打球に関する情報も記録されています。代表的な項目が次の4つです。

  • launch_speed:打球速度(Exit Velocity)
  • launch_angle:打球角度(Launch Angle)
  • hit_distance_sc:打球距離
  • bb_type:ゴロ、ライナー、フライなどの打球タイプ

これらを使うと、「ヒットだったか」だけではなく、どのようなコンタクトだったのかを分析できます。

この記事ではGoogle Colabを使い、pybaseball とpandasで打球データを抽出し、基本的な集計まで進めます。


1. 打球単位とは?

基礎編⑤では、

1行 = 1球

としてStatcastデータを見ました。

今回も元になるDataFrameは同じですが、その中から打球に関係する行だけを抽出します。

イメージは次のとおりです。

Statcastデータ
    ↓
1球 = 1行
    ↓
打球が記録された行を抽出
    ↓
打球速度・角度・距離・タイプを分析

例えば4球で三振になった打席には4球分の行がありますが、打球は発生していません。

一方、最後の球がヒットになった打席では、その球の行に打球データが記録されます。


2. Statcastデータを取得する

まずは1日分のデータを取得します。

from pybaseball import statcast

game_data = statcast(
    start_dt="2025-06-16",
    end_dt="2025-06-16"
)

display(game_data.head())

出力結果

index pitch_type game_date release_speed release_pos_x release_pos_z player_name batter pitcher events description spin_dir spin_rate_deprecated break_angle_deprecated break_length_deprecated zone des game_type stand p_throws home_team
1416 FF 2025-06-16 00:00:00 93.5 -2.44 5.35 Yates, Kirby 642180 489446 field_out hit_into_play <NA> <NA> <NA> <NA> 2 Tyler Wade pops out to third baseman Max Muncy. R L R LAD
1466 FS 2025-06-16 00:00:00 86.7 -2.47 5.17 Yates, Kirby 642180 489446 NaN called_strike <NA> <NA> <NA> <NA> 13 NaN R L R LAD
1536 FF 2025-06-16 00:00:00 93.0 -2.46 5.21 Yates, Kirby 642180 489446 NaN foul <NA> <NA> <NA> <NA> 3 NaN R L R LAD
1578 FS 2025-06-16 00:00:00 85.9 -2.39 5.18 Yates, Kirby 578428 489446 field_out hit_into_play <NA> <NA> <NA> <NA> 9 Jose Iglesias lines out to shortstop Mookie Betts. R R R LAD
1660 FF 2025-06-16 00:00:00 93.4 -2.35 5.38 Yates, Kirby 578428 489446 NaN foul <NA> <NA> <NA> <NA> 11 NaN R R R LAD

最初は短い期間で試すのがおすすめです。

pybaseballの公式ドキュメントでは、Baseball Savant側の取得制限に対応するため、長期間のリクエストは分割されることが説明されています。大量データを扱う場合は、処理時間やメモリ使用量にも注意しましょう。


3. 打球データだけを取り出す

最も簡単な方法は、launch_speed が記録されている行を抽出することです。

batted_balls = game_data[
    game_data["launch_speed"].notna()
].copy()

display(batted_balls.head())

出力結果

index pitch_type game_date release_speed release_pos_x release_pos_z player_name batter pitcher events description spin_dir spin_rate_deprecated break_angle_deprecated break_length_deprecated zone des game_type stand p_throws home_team
1416 FF 2025-06-16 00:00:00 93.5 -2.44 5.35 Yates, Kirby 642180 489446 field_out hit_into_play <NA> <NA> <NA> <NA> 2 Tyler Wade pops out to third baseman Max Muncy. R L R LAD
1536 FF 2025-06-16 00:00:00 93.0 -2.46 5.21 Yates, Kirby 642180 489446 NaN foul <NA> <NA> <NA> <NA> 3 NaN R L R LAD
1578 FS 2025-06-16 00:00:00 85.9 -2.39 5.18 Yates, Kirby 578428 489446 field_out hit_into_play <NA> <NA> <NA> <NA> 9 Jose Iglesias lines out to shortstop Mookie Betts. R R R LAD
1660 FF 2025-06-16 00:00:00 93.4 -2.35 5.38 Yates, Kirby 578428 489446 NaN foul <NA> <NA> <NA> <NA> 11 NaN R R R LAD
1678 FF 2025-06-16 00:00:00 94.0 -2.5 5.34 Yates, Kirby 578428 489446 NaN foul <NA> <NA> <NA> <NA> 11 NaN R R R LAD

notna() は「値が空欄ではない」という条件です。

つまり、

game_data["launch_speed"].notna()

によって、launch_speed が記録されている行だけを残しています。

Statcast公式ドキュメントでは、launch_speed はStatcastが追跡した打球速度で、一部の直接追跡されていない打球について推定値が含まれると説明されています。


4. 打球に関係する列を確認する

まずは必要な列だけ表示してみます。

batted_ball_columns = [
    "game_date",
    "game_pk",
    "at_bat_number",
    "pitch_number",
    "batter",
    "pitcher",
    "events",
    "pitch_name",
    "release_speed",
    "launch_speed",
    "launch_angle",
    "hit_distance_sc",
    "bb_type",
    "launch_speed_angle"
]

display(
    batted_balls[batted_ball_columns].head(20)
)

出力結果

index game_date game_pk at_bat_number pitch_number batter pitcher events pitch_name release_speed launch_speed launch_angle hit_distance_sc bb_type launch_speed_angle
1416 2025-06-16 00:00:00 777490 73 3 642180 489446 field_out 4-Seam Fastball 93.5 76.0 57 182 popup 3
1536 2025-06-16 00:00:00 777490 73 1 642180 489446 NaN 4-Seam Fastball 93.0 59.8 48 159 NaN <NA>
1578 2025-06-16 00:00:00 777490 72 4 578428 489446 field_out Split-Finger 85.9 98.5 5 167 line_drive 4
1660 2025-06-16 00:00:00 777490 72 3 578428 489446 NaN 4-Seam Fastball 93.4 81.0 43 262 NaN <NA>
1678 2025-06-16 00:00:00 777490 72 2 578428 489446 NaN 4-Seam Fastball 94.0 78.4 53 219 NaN <NA>
1772 2025-06-16 00:00:00 777490 72 1 578428 489446 NaN 4-Seam Fastball 93.3 66.6 48 189 NaN <NA>
1825 2025-06-16 00:00:00 777490 71 3 630105 489446 field_out Split-Finger 86.0 68.9 -17 5 ground_ball 2
852 2025-06-16 00:00:00 777490 70 1 605141 688158 field_out 4-Seam Fastball 95.3 91.1 54 238 fly_ball 3
967 2025-06-16 00:00:00 777490 68 1 669242 688158 field_out Slider 87.1 88.2 -16 5 ground_ball 2
994 2025-06-16 00:00:00 777490 67 5 624424 688158 field_out 4-Seam Fastball 96.4 96.7 7 146 line_drive 4
1077 2025-06-16 00:00:00 777490 67 2 624424 688158 NaN 4-Seam Fastball 96.7 66.2 64 164 NaN <NA>
1106 2025-06-16 00:00:00 777490 67 1 624424 688158 NaN 4-Seam Fastball 97.5 100.2 -3 34 NaN <NA>
1576 2025-06-16 00:00:00 777490 66 1 593428 656945 field_out 4-Seam Fastball 97.3 69.6 71 115 popup 3
1788 2025-06-16 00:00:00 777490 64 3 592518 656945 field_out 4-Seam Fastball 97.0 108.1 -7 14 ground_ball 2
1118 2025-06-16 00:00:00 777490 63 1 681624 688158 force_out Slider 86.9 104.1 -8 13 ground_ball 2
1276 2025-06-16 00:00:00 777490 62 1 571970 688158 NaN Curveball 82.3 67.7 -31 4 NaN <NA>
1296 2025-06-16 00:00:00 777490 61 7 669257 688158 single 4-Seam Fastball 98.3 102.0 2 66 ground_ball 4
1364 2025-06-16 00:00:00 777490 61 6 669257 688158 NaN Slider 88.2 77.0 -27 5 NaN <NA>
1456 2025-06-16 00:00:00 777490 61 4 669257 688158 NaN 4-Seam Fastball 96.6 79.0 16 185 NaN <NA>
1703 2025-06-16 00:00:00 777490 60 5 606192 688158 NaN Slider 87.4 71.3 67 127 NaN <NA>

ここから、

  • どの球種を打ったのか
  • 何mphの球だったのか
  • 打球速度は何mphだったのか
  • 打球角度は何度だったのか
  • どのくらい飛んだのか
  • ゴロ・ライナー・フライのどれだったのか

を確認できます。


5. launch_speed は打球速度

launch_speed はStatcastの**Exit Velocity(EV)**です。

単位はmphです。

display(
    batted_balls[
        [
            "events",
            "description",
            "launch_speed"
        ]
    ].head(20)
)

出力結果

index events description launch_speed
1416 field_out hit_into_play 76.0
1536 NaN foul 59.8
1578 field_out hit_into_play 98.5
1660 NaN foul 81.0
1678 NaN foul 78.4
1772 NaN foul 66.6
1825 field_out hit_into_play 68.9
852 field_out hit_into_play 91.1
967 field_out hit_into_play 88.2
994 field_out hit_into_play 96.7
1077 NaN foul 66.2
1106 NaN foul 100.2
1576 field_out hit_into_play 69.6
1788 field_out hit_into_play 108.1
1118 force_out hit_into_play 104.1
1276 NaN foul 67.7
1296 single hit_into_play 102.0
1364 NaN foul 77.0
1456 NaN foul 79.0
1703 NaN foul 71.3

平均打球速度は次のように計算できます。

avg_exit_velocity = (
    batted_balls["launch_speed"].mean()
)

print(f"平均打球速度: {avg_exit_velocity:.1f} mph")

出力結果

平均打球速度: 83.3 mph

ただし、複数の選手や球種をまとめて平均すると意味が分かりにくくなる場合があります。

実際の分析では、選手別、球種別、投手別などに分けて見ると傾向を把握しやすくなります。


6. launch_angle は打球角度

launch_angle は打球角度です。単位は度です。

display(
    batted_balls[
        [
            "events",
            "description",
            "launch_speed",
            "launch_angle"
        ]
    ].head(20)
)

出力結果

index events description launch_speed launch_angle
1416 field_out hit_into_play 76.0 57
1536 NaN foul 59.8 48
1578 field_out hit_into_play 98.5 5
1660 NaN foul 81.0 43
1678 NaN foul 78.4 53
1772 NaN foul 66.6 48
1825 field_out hit_into_play 68.9 -17
852 field_out hit_into_play 91.1 54
967 field_out hit_into_play 88.2 -16
994 field_out hit_into_play 96.7 7
1077 NaN foul 66.2 64
1106 NaN foul 100.2 -3
1576 field_out hit_into_play 69.6 71
1788 field_out hit_into_play 108.1 -7
1118 force_out hit_into_play 104.1 -8
1276 NaN foul 67.7 -31
1296 single hit_into_play 102.0 2
1364 NaN foul 77.0 -27
1456 NaN foul 79.0 16
1703 NaN foul 71.3 67

角度が低い打球、高い打球などを区別できます。

https://baseballsavant.mlb.com/csv-docs#launch_speed_angleから引用


7. hit_distance_sc は打球距離

hit_distance_sc はStatcastの打球距離に関する項目です。

display(
    batted_balls[
        [
            "launch_speed",
            "launch_angle",
            "hit_distance_sc"
        ]
    ].head(20)
)

出力結果

index launch_speed launch_angle hit_distance_sc
1416 76.0 57 182
1536 59.8 48 159
1578 98.5 5 167
1660 81.0 43 262
1678 78.4 53 219
1772 66.6 48 189
1825 68.9 -17 5
852 91.1 54 238
967 88.2 -16 5
994 96.7 7 146
1077 66.2 64 164
1106 100.2 -3 34
1576 69.6 71 115
1788 108.1 -7 14
1118 104.1 -8 13
1276 67.7 -31 4
1296 102.0 2 66
1364 77.0 -27 5
1456 79.0 16 185
1703 71.3 67 127

日本向けの分析では、フィートをメートルに変換することもできます。

batted_balls["hit_distance_m"] = (
    batted_balls["hit_distance_sc"] * 0.3048
)

display(
    batted_balls[
        [
            "hit_distance_sc",
            "hit_distance_m"
        ]
    ].head(20)
)

出力結果

index hit_distance_sc hit_distance_m
1416 182 55.473600000000005
1536 159 48.4632
1578 167 50.9016
1660 262 79.8576
1678 219 66.7512
1772 189 57.607200000000006
1825 5 1.524
852 238 72.5424
967 5 1.524
994 146 44.500800000000005
1077 164 49.9872
1106 34 10.3632
1576 115 35.052
1788 14 4.2672
1118 13 3.9624
1276 4 1.2192
1296 66 20.1168
1364 5 1.524
1456 185 56.388000000000005
1703 127 38.7096

例えば400フィートは、

400 × 0.3048 ≒ 121.9m

です。

hit_distance_sc(打球飛距離)は、原則として「打球が最初に着地した地点、または野手のグローブなどに触れた地点」までのホームプレートからの水平距離を表しています。


8. bb_type で打球タイプを見る

bb_type は打球タイプです。

代表的な分類は次のとおりです。

bb_type 意味
ground_ball ゴロ
line_drive ライナー
fly_ball フライ
popup ポップアップ
display(
    batted_balls[
        [
            "launch_speed",
            "launch_angle",
            "bb_type"
        ]
    ].head(30)
)

出力結果

index launch_speed launch_angle bb_type
1416 76.0 57 popup
1536 59.8 48 NaN
1578 98.5 5 line_drive
1660 81.0 43 NaN
1678 78.4 53 NaN
1772 66.6 48 NaN
1825 68.9 -17 ground_ball
852 91.1 54 fly_ball
967 88.2 -16 ground_ball
994 96.7 7 line_drive
1077 66.2 64 NaN
1106 100.2 -3 NaN
1576 69.6 71 popup
1788 108.1 -7 ground_ball
1118 104.1 -8 ground_ball
1276 67.7 -31 NaN
1296 102.0 2 ground_ball
1364 77.0 -27 NaN
1456 79.0 16 NaN
1703 71.3 67 NaN
1098 97.3 1 ground_ball
1399 75.4 0 ground_ball
1422 99.0 9 line_drive
1474 76.7 42 NaN
1750 83.1 28 line_drive
1175 77.2 -1 ground_ball
1543 72.6 -20 ground_ball
1753 87.5 24 line_drive
1849 89.1 68 popup
383 84.7 24 line_drive

打球タイプの件数は value_counts() で確認できます。

bb_type_counts = (
    batted_balls["bb_type"]
    .value_counts(dropna=False)
)

display(bb_type_counts)

出力結果

bb_type count
NaN 321
ground_ball 150
line_drive 76
fly_ball 76
popup 34

割合を確認するなら、

bb_type_ratio = (
    batted_balls["bb_type"]
    .value_counts(normalize=True, dropna=False)
    .mul(100)
    .round(1)
)

display(bb_type_ratio)

出力結果

bb_type proportion
NaN 48.9
ground_ball 22.8
line_drive 11.6
fly_ball 11.6
popup 5.2

9. 選手別の平均打球速度を計算する

選手別に打球速度を集計してみます。

batter_summary = (
    batted_balls
    .groupby("batter")
    .agg(
        batted_balls=("launch_speed", "count"),
        avg_exit_velocity=("launch_speed", "mean"),
        max_exit_velocity=("launch_speed", "max"),
        avg_launch_angle=("launch_angle", "mean")
    )
    .reset_index()
    .sort_values(
        "avg_exit_velocity",
        ascending=False
    )
)

display(batter_summary.head(20))

出力結果

index batter batted_balls avg_exit_velocity max_exit_velocity avg_launch_angle
134 810938 1 104.5 104.5 3.0
115 691594 1 103.3 103.3 -4.0
119 692225 1 102.3 102.3 -10.0
53 663993 1 101.7 101.7 -14.0
13 592450 3 100.93333333333334 110.7 9.333333333333334
62 666018 2 100.4 106.4 14.5
22 605170 3 99.46666666666665 103.4 -2.6666666666666665
102 682663 4 99.425 107.7 6.0
94 680776 7 98.55714285714285 110.0 20.142857142857142
130 702284 1 97.6 97.6 7.0
54 664040 4 97.35 109.9 3.25
7 519317 6 96.53333333333335 111.1 -5.5
70 668227 3 96.26666666666667 108.6 26.0
8 545361 4 95.35 104.6 21.5
89 676694 2 94.65 103.3 -3.0
20 605137 1 93.9 93.9 -6.0
129 701762 6 92.0 111.7 2.6666666666666665
80 669911 3 90.96666666666665 105.5 10.666666666666666
92 679032 1 90.8 90.8 -12.0
118 691785 4 90.75 103.0 0.0

ここでは batter のMLB Player IDを分析のキーにしています。

選手名を表示したい場合は、IDから選手名を取得して後から結合する方法が安全です。

また、平均値だけでなく batted_balls も必ず確認しましょう。

1球だけの平均と100球以上の平均では、分析上の意味が大きく違うためです。


10. 特定の打者だけを分析する

特定の選手に絞る場合は batter を使えます。

batter_id = 660271

batter_balls = batted_balls[
    batted_balls["batter"] == batter_id
].copy()

display(
    batter_balls[
        [
            "game_date",
            "events",
            "pitch_name",
            "release_speed",
            "launch_speed",
            "launch_angle",
            "hit_distance_sc",
            "bb_type"
        ]
    ]
)

出力結果

index game_date events pitch_name release_speed launch_speed launch_angle hit_distance_sc bb_type
258 2025-06-16 00:00:00 single 4-Seam Fastball 98.3 87.9 25 274 line_drive
277 2025-06-16 00:00:00 NaN 4-Seam Fastball 99.5 81.5 69 163 NaN
615 2025-06-16 00:00:00 double Slider 91.5 105.2 17 337 line_drive
1713 2025-06-16 00:00:00 NaN Slider 91.4 77.2 -32 4 NaN

660271 は分析対象のMLB Player IDに置き換えてください。

選手IDを検索する場合は、pybaseballの playerid_lookup() を利用できます。

from pybaseball import playerid_lookup

playerid_lookup("ohtani", "shohei")

出力結果

index name_last name_first key_mlbam key_retro key_bbref key_fangraphs mlb_played_first mlb_played_last
0 ohtani shohei 660271 ohtas001 ohtansh01 19755 2018.0 2026.0

11. ハードヒットを調べる

Statcastでは、95mph以上の打球をHard Hitと定義しています。

そのため、95mph以上の打球を抽出する基本コードは次のとおりです。

hard_hit = batted_balls[
    batted_balls["launch_speed"] >= 95
].copy()

display(
    hard_hit[
        [
            "batter",
            "events",
            "launch_speed",
            "launch_angle",
            "hit_distance_sc",
            "bb_type"
        ]
    ].head(20)
)

出力結果

index batter events launch_speed launch_angle hit_distance_sc bb_type
1578 578428 field_out 98.5 5 167 line_drive
994 624424 field_out 96.7 7 146 line_drive
1106 624424 NaN 100.2 -3 34 NaN
1788 592518 field_out 108.1 -7 14 ground_ball
1118 681624 force_out 104.1 -8 13 ground_ball
1296 669257 single 102.0 2 66 ground_ball
1098 518692 single 97.3 1 55 ground_ball
1422 665487 single 99.0 9 184 line_drive
461 657757 double 97.1 7 147 line_drive
488 592518 home_run 99.9 35 353 fly_ball
94 606192 field_out 110.3 -3 25 ground_ball
282 669242 single 105.8 16 252 line_drive
388 571970 single 108.2 17 309 line_drive
681 642180 field_out 96.0 5 88 ground_ball
820 593428 double 100.1 17 319 line_drive
883 657757 NaN 97.0 -1 27 NaN
615 660271 double 105.2 17 337 line_drive
647 669242 field_out 105.7 -17 5 ground_ball
801 681624 double 95.4 11 228 line_drive
1209 650333 field_out 96.9 -5 11 ground_ball

件数と割合も計算できます。

print("ハードヒット数:", len(hard_hit))

hard_hit_rate = (
    len(hard_hit) / len(batted_balls) * 100
)

print(f"ハードヒット率: {hard_hit_rate:.1f}%")

出力結果

ハードヒット数: 173 ハードヒット率: 26.3%


12. launch_speed_angle とBarrel

Statcastには、打球速度と打球角度の組み合わせを分類する launch_speed_angle があります。

display(
    batted_balls[
        [
            "launch_speed",
            "launch_angle",
            "launch_speed_angle"
        ]
    ].head(20)
)

出力結果

index launch_speed launch_angle launch_speed_angle
1416 76.0 57 3
1536 59.8 48 <NA>
1578 98.5 5 4
1660 81.0 43 <NA>
1678 78.4 53 <NA>
1772 66.6 48 <NA>
1825 68.9 -17 2
852 91.1 54 3
967 88.2 -16 2
994 96.7 7 4
1077 66.2 64 <NA>
1106 100.2 -3 <NA>
1576 69.6 71 3
1788 108.1 -7 2
1118 104.1 -8 2
1276 67.7 -31 <NA>
1296 102.0 2 4
1364 77.0 -27 <NA>
1456 79.0 16 <NA>
1703 71.3 67 <NA>

Statcastでは、

  1. Weak
  2. Topped
  3. Under
  4. Flare/Burner
  5. Solid Contact
  6. Barrel

などに分類されます。

https://baseballsavant.mlb.com/csv-docs#launch_speed_angleから引用


13. ヒットになった打球だけを取り出す

events と組み合わせると、ヒットになった打球を確認できます。

hit_events = [
    "single",
    "double",
    "triple",
    "home_run"
]

hits = batted_balls[
    batted_balls["events"].isin(hit_events)
].copy()

display(
    hits[
        [
            "batter",
            "events",
            "launch_speed",
            "launch_angle",
            "hit_distance_sc",
            "bb_type"
        ]
    ].head(20)
)

出力結果

index batter events launch_speed launch_angle hit_distance_sc bb_type
1296 669257 single 102.0 2 66 ground_ball
1098 518692 single 97.3 1 55 ground_ball
1422 665487 single 99.0 9 184 line_drive
461 657757 double 97.1 7 147 line_drive
488 592518 home_run 99.9 35 353 fly_ball
227 605141 single 83.2 24 285 line_drive
258 660271 single 87.9 25 274 line_drive
282 669242 single 105.8 16 252 line_drive
388 571970 single 108.2 17 309 line_drive
420 669257 double 81.1 31 279 fly_ball
490 606192 single 68.2 -40 2 ground_ball
820 593428 double 100.1 17 319 line_drive
615 660271 double 105.2 17 337 line_drive
801 681624 double 95.4 11 228 line_drive
1353 650333 single 95.6 12 224 line_drive
1647 665487 single 74.6 32 253 fly_ball
1102 666160 home_run 98.8 30 368 fly_ball
1255 642731 single 110.8 8 197 line_drive
1723 696100 home_run 105.2 26 400 fly_ball
64 695578 home_run 104.6 25 373 fly_ball

これで、

ヒットになった打球は、どのくらいの速度・角度だったのか?

を調べられます。


14. 投手側から被打球を見る

打球分析は打者だけでなく、投手にも使えます。

pitcher_summary = (
    batted_balls
    .groupby("pitcher")
    .agg(
        batted_balls=("launch_speed", "count"),
        avg_exit_velocity=("launch_speed", "mean"),
        max_exit_velocity=("launch_speed", "max")
    )
    .reset_index()
    .sort_values(
        "avg_exit_velocity",
        ascending=False
    )
)

display(pitcher_summary.head(20))

出力結果

index pitcher batted_balls avg_exit_velocity max_exit_velocity
42 680767 2 103.80000000000001 105.9
6 592836 2 102.44999999999999 107.6
21 650556 2 95.15 111.7
44 681882 5 95.02000000000001 110.4
20 647315 6 94.68333333333334 104.8
1 458677 4 93.775 106.9
15 640448 9 90.78888888888889 110.8
31 666171 3 89.13333333333333 104.3
45 681911 1 89.1 89.1
33 667755 37 88.94324324324324 111.1
55 695418 7 88.91428571428571 102.5
25 656945 2 88.85 108.1
14 623474 4 88.25 104.6
53 690953 29 87.48620689655172 107.7
41 678368 15 87.46666666666667 102.1
34 669302 23 87.17826086956521 110.0
39 676508 21 87.1047619047619 100.1
54 695243 1 86.0 86.0
51 688158 11 85.77272727272727 104.1
49 687765 32 85.159375 109.2

これで投手ごとの被打球速度を確認できます。


15. 打球速度と打球角度を可視化する

Google Colabでは、matplotlibを使って散布図を作れます。

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 6))

plt.scatter(
    batted_balls["launch_speed"],
    batted_balls["launch_angle"],
    alpha=0.5
)

plt.xlabel("Exit Velocity (mph)")
plt.ylabel("Launch Angle (degrees)")
plt.title("Exit Velocity vs Launch Angle")

plt.show()

出力結果 Exit Velocity vs Launch Angle

横軸が打球速度、縦軸が打球角度です。

この図を見ることで、打球がどのような速度・角度の組み合わせに分布しているのかを直感的に確認できます。


まとめ

今回は、pybaseball を使ってMLBのStatcastデータから打球単位のデータを抽出する方法を解説しました。

特に重要なのは次の項目です。

列名 内容
launch_speed 打球速度(Exit Velocity)
launch_angle 打球角度
hit_distance_sc 打球距離に関するStatcast項目
bb_type ゴロ・ライナー・フライなど
launch_speed_angle 打球速度と角度による分類
events 打席の結果
batter 打者のMLB Player ID
pitcher 投手のMLB Player ID

打球分析では、

打球速度だけでなく、打球速度・角度・距離・打球タイプを組み合わせて見る

ことがポイントです。


次回の記事

次回は、

【pybaseball基礎編⑦】投球単位のデータ取得

を予定しています。

基礎編⑤では1球単位の基本データ、基礎編⑥では打球データを扱いました。

基礎編⑦では投手側に戻り、

  • 投球速度
  • 回転数
  • 回転軸
  • リリース位置
  • 球種
  • 投球位置
  • 球種ごとの特徴

などを使って、1球の投球そのものを詳しく分析する方法を扱います。


データ参照元

本記事では、MLBのStatcastデータをpybaseballから取得して分析しています。

Statcastのデータ項目については、MLBのBaseball Savantが公開しているStatcast Search CSV Documentationを参照しています。

Statcast Search CSV Documentation

pybaseballは、Baseball SavantのStatcastデータをPythonから取得し、pandasのDataFrameとして扱いやすくするためのライブラリです。

pybaseball GitHub

データを利用・公開する場合は、利用元の最新の規約、データ提供条件、各サービスの利用条件を確認してください。


動作環境

本記事ではGoogle Colabを利用しています。

Pythonとpybaseballのバージョンは、以下のコードで確認できます。

import sys
import pybaseball

print("Python:", sys.version)
print("pybaseball:", pybaseball.__version__)

出力結果

Python: 3.13.15 (main, Aug  6 2026, 11:06:22) [GCC 13.3.0]
pybaseball: 2.2.7

Hugo で構築されています。
テーマ Stack は Jimmy によって設計されています。