# pybaseball / グラフの題名に対戦選手名を入れる方法を探った(藤浪投手のデータを確認しつつ) **Published by:** [Shogaku](https://paragraph.com/@shogaku/) **Published on:** 2023-04-19 **URL:** https://paragraph.com/@shogaku/pybaseball ## Content 藤浪投手のデータを確認しつつ、各選手への投球結果(何球目など)をグラフに表示。 グラフの題名に対戦選手名を入れる方法を探った3試合の結果 https://baseballsavant.mlb.com/savant-player/shintaro-fujinami-660261?stats=gamelogs-r-pitching-mlb&season=2023データ取得!pip install pybaseball from pybaseball import statcast import pandas as pd from pybaseball import statcast dates = [ '2023-04-01', '2023-04-08', '2023-04-15' ] # Create an empty DataFrame to store the data df_660261_all_dates = pd.DataFrame() # Fetch data for each date and concatenate for date in dates: df_single_day = statcast(start_dt=date, end_dt=date) df_660261_single_day = df_single_day[df_single_day['pitcher'] == 660261] df_660261_all_dates = pd.concat([df_660261_all_dates, df_660261_single_day]) # Reset the index of the final DataFrame df_660261_all_dates.reset_index(drop=True, inplace=True) 球種# 投球結果を抽出 df_660261 = df_660261_all_dates # df_660261のpitch_typeカラムに含まれるユニークな球種を確認する unique_pitch_types = df_660261['pitch_type'].unique() # 確認した球種を表示する print(unique_pitch_types) 結果['FF' 'SL' 'FS' 'ST' 'CU' 'SI'] FF: Four-Seam Fastball - 4シームファストボールSL: Slider - スライダーFS: Splitter - スプリッターST: Slutter - スライダー or カッターCU: Curveball - カーブSI: Sinker - シンカー (2シームファストボール)球種カウントimport pandas as pd def pitch_counts(df): # 左打者と右打者に対する投球データを抽出 df_L = df[df['stand'] == 'L'] df_R = df[df['stand'] == 'R'] # 各カテゴリーでの球種の出現回数をカウント total_counts = df['pitch_type'].value_counts() left_counts = df_L['pitch_type'].value_counts() right_counts = df_R['pitch_type'].value_counts() # 出現回数をデータフレームにまとめる pitch_counts_table = pd.DataFrame({'Total': total_counts, 'Left Batter': left_counts, 'Right Batter': right_counts}) # NaNを0に置き換える pitch_counts_table.fillna(0, inplace=True) # カウントを整数に変換する pitch_counts_table = pitch_counts_table.astype(int) return pitch_counts_table # 続けて、球種カウントのコードを実行します。 # Split the data by date df_0401 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-01'] df_0408 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-08'] df_0415 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-15'] # Get pitch counts for each date pitch_counts_0401 = pitch_counts(df_0401) pitch_counts_0408 = pitch_counts(df_0408) pitch_counts_0415 = pitch_counts(df_0415) # Display the results print("2023年4月1日の球種カウント:") print(pitch_counts_0401) print("\n2023年4月8日の球種カウント:") print(pitch_counts_0408) print("\n2023年4月15日の球種カウント:") print(pitch_counts_0415) 球種カウント(円グラフ)import matplotlib.pyplot as plt def plot_pitch_distribution(df, date): df_L = df[df['stand'] == 'L'] df_R = df[df['stand'] == 'R'] fig, axs = plt.subplots(1, 3, figsize=(18, 6)) plt.suptitle(f'Pitch Distribution on {date}') colors = {'FF': 'red', 'SL': 'blue', 'FS': 'green', 'ST': 'orange', 'CU': 'purple', 'SI': 'brown'} # Total df['pitch_type'].value_counts().plot(kind='pie', ax=axs[0], autopct='%.1f%%', colors=[colors[key] for key in df['pitch_type'].value_counts().index]) axs[0].set_title('Total') axs[0].set_ylabel('') # vs Left batter df_L['pitch_type'].value_counts().plot(kind='pie', ax=axs[1], autopct='%.1f%%', colors=[colors[key] for key in df_L['pitch_type'].value_counts().index]) axs[1].set_title('vs Left batter') axs[1].set_ylabel('') # vs Right batter df_R['pitch_type'].value_counts().plot(kind='pie', ax=axs[2], autopct='%.1f%%', colors=[colors[key] for key in df_R['pitch_type'].value_counts().index]) axs[2].set_title('vs Right batter') axs[2].set_ylabel('') plt.show() df_2023_04_01 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-01'] df_2023_04_08 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-08'] df_2023_04_15 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-15'] plot_pitch_distribution(df_2023_04_01, '2023-04-01') plot_pitch_distribution(df_2023_04_08, '2023-04-08') plot_pitch_distribution(df_2023_04_15, '2023-04-15') 投球コースimport matplotlib.pyplot as plt def plot_pitch_location(df, date): # データを pitch_type ごとにグループ分けする grouped = df.groupby('pitch_type') colors = {'FF': 'red', 'SL': 'blue', 'FS': 'green', 'ST': 'orange', 'CU': 'purple', 'SI': 'brown'} # pitch_type ごとに、'plate_x' を X 軸、'plate_z' を Y 軸とした散布図を作成する for pitch_type, data in grouped: plt.scatter(data['plate_x'], data['plate_z'], label=pitch_type, color=colors[pitch_type]) # ストライクゾーン x = [-0.88, 0.88, 0.88, -0.88, -0.88] y = [1.51, 1.51, 3.4, 3.4, 1.51] plt.fill(x, y, color='r', alpha=0.3) # 凡例を表示する plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0) plt.xlim(-3, 4) plt.ylim(-3, 7) plt.xlabel('Plate X') plt.ylabel('Plate Z') # 罫線 plt.grid(which='both', linestyle='--', color='gray', alpha=0.5) plt.title(f'Pitch Location on {date}') # グラフを表示する plt.show() df_2023_04_01 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-01'] df_2023_04_08 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-08'] df_2023_04_15 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-15'] plot_pitch_location(df_2023_04_01, '2023-04-01') plot_pitch_location(df_2023_04_08, '2023-04-08') plot_pitch_location(df_2023_04_15, '2023-04-15') 投球コース(球種ごと)import matplotlib.pyplot as plt def plot_pitch_location_by_date(df_1, df_2, df_3): combined_df = pd.concat([df_1, df_2, df_3]) grouped = combined_df.groupby('pitch_type') nrows = 3 ncols = 2 titles = [] fig, axes = plt.subplots(nrows=nrows, ncols=ncols, figsize=(10, 15)) for idx, (pitch_type, data) in enumerate(grouped): titles.append(pitch_type) row = idx // ncols col = idx % ncols ax = axes[row][col] data_1 = data[data.index.isin(df_1.index)] data_2 = data[data.index.isin(df_2.index)] data_3 = data[data.index.isin(df_3.index)] ax.scatter(data_1['plate_x'], data_1['plate_z'], label='2023-04-01', color='blue') ax.scatter(data_2['plate_x'], data_2['plate_z'], label='2023-04-08', color='red') ax.scatter(data_3['plate_x'], data_3['plate_z'], label='2023-04-15', color='green') x = [-0.88, 0.88, 0.88, -0.88, -0.88] y = [1.51, 1.51, 3.4, 3.4, 1.51] ax.fill(x, y, color='r', alpha=0.3) ax.set_title(pitch_type) ax.set_xlabel('Plate X') ax.set_ylabel('Plate Z') ax.grid(which='both', linestyle='--', color='gray', alpha=0.5) ax.legend() ax.set_xlim(-3, 4) # X軸の最小値と最大値を設定 ax.set_ylim(-3, 7) # Y軸の最小値と最大値を設定 plt.tight_layout() plt.show() df_2023_04_01 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-01'] df_2023_04_08 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-08'] df_2023_04_15 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-15'] plot_pitch_location_by_date(df_2023_04_01, df_2023_04_08, df_2023_04_15) リリースポイントimport matplotlib.pyplot as plt def plot_release_point(df, date): grouped = df.groupby('pitch_type') colors = {'FF': 'blue', 'SL': 'red', 'FS': 'green', 'ST': 'orange', 'CU': 'purple', 'SI': 'brown'} for pitch_type, data in grouped: plt.scatter(data['release_pos_x'], data['release_pos_z'], label=pitch_type, color=colors[pitch_type]) plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0) plt.xlabel('Release Pos X') plt.ylabel('Release Pos Z') plt.grid(which='both', linestyle='--', color='gray', alpha=0.5) plt.title(f'Release Point for {date}') plt.xlim(-3, -1) plt.ylim(4.5, 6.5) plt.show() df_2023_04_01 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-01'] df_2023_04_08 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-08'] df_2023_04_15 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-15'] plot_release_point(df_2023_04_01, '2023-04-01') plot_release_point(df_2023_04_08, '2023-04-08') plot_release_point(df_2023_04_15, '2023-04-15') リリースポイント(球種ごと)import matplotlib.pyplot as plt def plot_release_point_by_date(df_1, df_2, df_3): combined_df = pd.concat([df_1, df_2, df_3]) grouped = combined_df.groupby('pitch_type') nrows = 3 ncols = 2 titles = [] fig, axes = plt.subplots(nrows=nrows, ncols=ncols, figsize=(10, 15)) for idx, (pitch_type, data) in enumerate(grouped): titles.append(pitch_type) row = idx // ncols col = idx % ncols ax = axes[row][col] data_1 = data[data.index.isin(df_1.index)] data_2 = data[data.index.isin(df_2.index)] data_3 = data[data.index.isin(df_3.index)] ax.scatter(data_1['release_pos_x'], data_1['release_pos_z'], label='2023-04-01', color='blue') ax.scatter(data_2['release_pos_x'], data_2['release_pos_z'], label='2023-04-08', color='red') ax.scatter(data_3['release_pos_x'], data_3['release_pos_z'], label='2023-04-15', color='green') ax.set_title(pitch_type) ax.set_xlabel('Release Pos X') ax.set_ylabel('Release Pos Z') ax.grid(which='both', linestyle='--', color='gray', alpha=0.5) ax.legend() # Set the limits for X and Y axes ax.set_xlim(-3, -1) ax.set_ylim(4.5, 6.5) plt.tight_layout() plt.show() df_2023_04_01 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-01'] df_2023_04_08 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-08'] df_2023_04_15 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-15'] plot_release_point_by_date(df_2023_04_01, df_2023_04_08, df_2023_04_15) スピンレート(球種ごと) / Boxplotimport matplotlib.pyplot as plt import pandas as pd def plot_spin_rate_by_date_boxplot(df_1, df_2, df_3, pitch_types, dates): pitch_types = [pt for pt in pitch_types if pt is not None and pd.notna(pt)] # nan を除外 fig, axs = plt.subplots(len(pitch_types), 1, figsize=(8, len(pitch_types) * 4)) for i, pitch_type in enumerate(pitch_types): ax = axs[i] grouped_1 = df_1[df_1['pitch_type'] == pitch_type].dropna(subset=['release_spin_rate']) grouped_2 = df_2[df_2['pitch_type'] == pitch_type].dropna(subset=['release_spin_rate']) grouped_3 = df_3[df_3['pitch_type'] == pitch_type].dropna(subset=['release_spin_rate']) data_to_plot = [] labels = [] if not grouped_1.empty: data_to_plot.append(grouped_1['release_spin_rate']) labels.append(dates[0]) if not grouped_2.empty: data_to_plot.append(grouped_2['release_spin_rate']) labels.append(dates[1]) if not grouped_3.empty: data_to_plot.append(grouped_3['release_spin_rate']) labels.append(dates[2]) if data_to_plot: bp = ax.boxplot(data_to_plot, labels=labels) for j, d in enumerate(data_to_plot): mean_val = d.mean() ax.text(j + 0.8, mean_val, f"{mean_val:.1f}", ha='center', va='bottom', fontsize=10, color='blue') ax.set_title(f"Pitch Type: {pitch_type}") ax.set_xlabel('Date') ax.set_ylabel('Release Spin Rate') # 罫線 ax.grid(which='both', linestyle='--', color='gray', alpha=0.5) fig.suptitle('Release Spin Rate by Date and Pitch Type', fontsize=16, y=1.02) plt.tight_layout(pad=3) plt.show() pitch_types_1 = df_2023_04_01['pitch_type'].unique() pitch_types_2 = df_2023_04_08['pitch_type'].unique() pitch_types_3 = df_2023_04_15['pitch_type'].unique() # すべての日に存在する球種を取得 all_pitch_types = set(pitch_types_1) | set(pitch_types_2) | set(pitch_types_3) dates = ["2023-04-01", "2023-04-08", "2023-04-15"] plot_spin_rate_by_date_boxplot(df_2023_04_01, df_2023_04_08, df_2023_04_15, all_pitch_types, dates) スピード(球種ごと) / Boxplotdef plot_release_speed_by_date_boxplot(df_1, df_2, df_3, pitch_types, dates): pitch_types = [pt for pt in pitch_types if pt is not None and pd.notna(pt)] # nan を除外 fig, axs = plt.subplots(len(pitch_types), 1, figsize=(8, len(pitch_types) * 4)) for i, pitch_type in enumerate(pitch_types): ax = axs[i] grouped_1 = df_1[df_1['pitch_type'] == pitch_type].dropna(subset=['release_speed']) grouped_2 = df_2[df_2['pitch_type'] == pitch_type].dropna(subset=['release_speed']) grouped_3 = df_3[df_3['pitch_type'] == pitch_type].dropna(subset=['release_speed']) data_to_plot = [] labels = [] if not grouped_1.empty: data_to_plot.append(grouped_1['release_speed']) labels.append(dates[0]) if not grouped_2.empty: data_to_plot.append(grouped_2['release_speed']) labels.append(dates[1]) if not grouped_3.empty: data_to_plot.append(grouped_3['release_speed']) labels.append(dates[2]) if data_to_plot: bp = ax.boxplot(data_to_plot, labels=labels) for j, d in enumerate(data_to_plot): mean_val = d.mean() ax.text(j + 0.8, mean_val, f"{mean_val:.1f}", ha='center', va='bottom', fontsize=10, color='blue') ax.set_title(f"Pitch Type: {pitch_type}") ax.set_xlabel('Date') ax.set_ylabel('Release Speed') # 罫線 ax.grid(which='both', linestyle='--', color='gray', alpha=0.5) fig.suptitle('Release Speed by Date and Pitch Type', fontsize=16, y=1.02) plt.tight_layout(pad=3) plt.show() # 2023年4月1日、4月8日、4月15日のデータに対してリリーススピードをプロット dates = ['2023-04-01', '2023-04-08', '2023-04-15'] plot_release_speed_by_date_boxplot(df_2023_04_01, df_2023_04_08, df_2023_04_15, all_pitch_types, dates) スピード(球種ごと) / Boxplot ※kmへ換算def plot_release_speed_by_date_boxplot_km(df_1, df_2, df_3, pitch_types, dates): pitch_types = [pt for pt in pitch_types if pt is not None and pd.notna(pt)] # nan を除外 fig, axs = plt.subplots(len(pitch_types), 1, figsize=(8, len(pitch_types) * 4)) for i, pitch_type in enumerate(pitch_types): ax = axs[i] grouped_1 = df_1[df_1['pitch_type'] == pitch_type].dropna(subset=['release_speed']) grouped_2 = df_2[df_2['pitch_type'] == pitch_type].dropna(subset=['release_speed']) grouped_3 = df_3[df_3['pitch_type'] == pitch_type].dropna(subset=['release_speed']) data_to_plot = [] labels = [] if not grouped_1.empty: data_to_plot.append(grouped_1['release_speed'] * 1.60934) labels.append(dates[0]) if not grouped_2.empty: data_to_plot.append(grouped_2['release_speed'] * 1.60934) labels.append(dates[1]) if not grouped_3.empty: data_to_plot.append(grouped_3['release_speed'] * 1.60934) labels.append(dates[2]) if data_to_plot: bp = ax.boxplot(data_to_plot, labels=labels) for j, d in enumerate(data_to_plot): mean_val = d.mean() ax.text(j + 0.8, mean_val, f"{mean_val:.1f}", ha='center', va='bottom', fontsize=10, color='blue') ax.set_title(f"Pitch Type: {pitch_type}") ax.set_xlabel('Date') ax.set_ylabel('Release Speed (km/h)') # 罫線 ax.grid(which='both', linestyle='--', color='gray', alpha=0.5) fig.suptitle('Release Speed by Date and Pitch Type (km/h)', fontsize=16, y=1.02) plt.tight_layout(pad=3) plt.show() # 2023年4月1日、4月8日、4月15日のデータに対してリリーススピードをキロメートル単位でプロット dates = ['2023-04-01', '2023-04-08', '2023-04-15'] plot_release_speed_by_date_boxplot_km(df_2023_04_01, df_2023_04_08, df_2023_04_15, all_pitch_types, dates) リリースポイント ~ ホーム距離 (球種ごと) / Boxplotdef plot_release_extension_by_date_boxplot(df_1, df_2, df_3, pitch_types, dates): pitch_types = [pt for pt in pitch_types if pt is not None and pd.notna(pt)] # nan を除外 fig, axs = plt.subplots(len(pitch_types), 1, figsize=(8, len(pitch_types) * 4)) for i, pitch_type in enumerate(pitch_types): ax = axs[i] grouped_1 = df_1[df_1['pitch_type'] == pitch_type].dropna(subset=['release_extension']) grouped_2 = df_2[df_2['pitch_type'] == pitch_type].dropna(subset=['release_extension']) grouped_3 = df_3[df_3['pitch_type'] == pitch_type].dropna(subset=['release_extension']) data_to_plot = [] labels = [] if not grouped_1.empty: data_to_plot.append(grouped_1['release_extension']) labels.append(dates[0]) if not grouped_2.empty: data_to_plot.append(grouped_2['release_extension']) labels.append(dates[1]) if not grouped_3.empty: data_to_plot.append(grouped_3['release_extension']) labels.append(dates[2]) if data_to_plot: bp = ax.boxplot(data_to_plot, labels=labels) for j, d in enumerate(data_to_plot): mean_val = d.mean() ax.text(j + 0.8, mean_val, f"{mean_val:.1f}", ha='center', va='bottom', fontsize=10, color='blue') ax.set_title(f"Pitch Type: {pitch_type}") ax.set_xlabel('Date') ax.set_ylabel('Release Extension (ft)') # 罫線 ax.grid(which='both', linestyle='--', color='gray', alpha=0.5) fig.suptitle('Release Extension by Date and Pitch Type (ft)', fontsize=16, y=1.02) plt.tight_layout(pad=3) plt.show() # 2023年4月1日、4月8日、4月15日のデータに対してリリースエクステンションをプロット dates = ['2023-04-01', '2023-04-08', '2023-04-15'] plot_release_extension_by_date_boxplot(df_2023_04_01, df_2023_04_08, df_2023_04_15, all_pitch_types, dates) 対戦打者・結果# 2023年4月15日のデータをフィルタリング df_660261_2023_04_15 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-15'] # 必要な列を選択 df_660261_2023_04_15_results = df_660261_2023_04_15[['batter', 'events', 'des']] # 2023年4月15日のデータをフィルタリング df_660261_2023_04_15 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-15'] # events列がNaNでない行をフィルタリング df_660261_2023_04_15_results_filtered = df_660261_2023_04_15_results.dropna(subset=['events']) # 結果を表示 print(df_660261_2023_04_15_results_filtered) 結果 batter events des 134 596129 walk Daniel Vogelbach walks. 140 592192 home_run Mark Canha homers (2) on a fly ball to left fi... 144 643446 field_out Jeff McNeil grounds out, first baseman Jesus A... 147 624413 field_out Pete Alonso grounds out, shortstop Aledmys Dia... 148 596019 field_out Francisco Lindor grounds out, second baseman T... 154 516782 hit_by_pitch Starling Marte hit by pitch. 156 607043 field_out Brandon Nimmo lines out sharply to right field... 159 682626 strikeout Francisco Alvarez strikes out on a foul tip. 164 641645 walk Luis Guillorme walks. 168 596129 field_out Daniel Vogelbach grounds out, third baseman Ja... 172 592192 field_out Mark Canha flies out sharply to center fielder... 175 643446 field_out Jeff McNeil grounds out to first baseman Jesus... 178 624413 home_run Pete Alonso homers (7) on a fly ball to left f... 180 596019 field_out Francisco Lindor grounds out, second baseman T... 186 516782 field_out Starling Marte flies out sharply to center fie... 190 607043 single Brandon Nimmo singles on a line drive to right... 195 682626 field_out Francisco Alvarez flies out to second baseman ... 196 641645 strikeout Luis Guillorme strikes out swinging. 201 596129 field_out Daniel Vogelbach grounds out, first baseman Je... 204 592192 strikeout Mark Canha strikes out swinging. 209 643446 field_out Jeff McNeil flies out to center fielder Esteur... 211 624413 strikeout Pete Alonso strikes out swinging. 214 596019 double Francisco Lindor doubles (6) on a ground ball ... 218 516782 field_out Starling Marte flies out to left fielder Conne... 220 607043 strikeout Brandon Nimmo strikes out swinging. 対戦打者・結果(並び替え)# 2023年4月15日のデータをフィルタリング df_660261_2023_04_15 = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-15'] # 必要な列を選択 df_660261_2023_04_15_results = df_660261_2023_04_15[['batter', 'events', 'des', 'at_bat_number']] # events列がNaNでない行をフィルタリング df_660261_2023_04_15_results_filtered = df_660261_2023_04_15_results.dropna(subset=['events']) # at_bat_number 列を使って df_660261_2023_04_15_results_filtered をソート df_660261_2023_04_15_results_filtered_sorted = df_660261_2023_04_15_results_filtered.sort_values(by='at_bat_number') # 結果を表示 print(df_660261_2023_04_15_results_filtered_sorted) 結果 batter events des \ 220 607043 strikeout Brandon Nimmo strikes out swinging. 218 516782 field_out Starling Marte flies out to left fielder Conne... 214 596019 double Francisco Lindor doubles (6) on a ground ball ... 211 624413 strikeout Pete Alonso strikes out swinging. 209 643446 field_out Jeff McNeil flies out to center fielder Esteur... 204 592192 strikeout Mark Canha strikes out swinging. 201 596129 field_out Daniel Vogelbach grounds out, first baseman Je... 196 641645 strikeout Luis Guillorme strikes out swinging. 195 682626 field_out Francisco Alvarez flies out to second baseman ... 190 607043 single Brandon Nimmo singles on a line drive to right... 186 516782 field_out Starling Marte flies out sharply to center fie... 180 596019 field_out Francisco Lindor grounds out, second baseman T... 178 624413 home_run Pete Alonso homers (7) on a fly ball to left f... 175 643446 field_out Jeff McNeil grounds out to first baseman Jesus... 172 592192 field_out Mark Canha flies out sharply to center fielder... 168 596129 field_out Daniel Vogelbach grounds out, third baseman Ja... 164 641645 walk Luis Guillorme walks. 159 682626 strikeout Francisco Alvarez strikes out on a foul tip. 156 607043 field_out Brandon Nimmo lines out sharply to right field... 154 516782 hit_by_pitch Starling Marte hit by pitch. 148 596019 field_out Francisco Lindor grounds out, second baseman T... 147 624413 field_out Pete Alonso grounds out, shortstop Aledmys Dia... 144 643446 field_out Jeff McNeil grounds out, first baseman Jesus A... 140 592192 home_run Mark Canha homers (2) on a fly ball to left fi... 134 596129 walk Daniel Vogelbach walks. 各打者との対戦結果import matplotlib.pyplot as plt # 2023年4月15日のデータをフィルタリング df_660261_fujinami = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-15'] unique_batters = sorted(df_660261_fujinami['at_bat_number'].unique()) nrows = (len(unique_batters) + 1) // 2 ncols = 2 fig, axs = plt.subplots(nrows, ncols, figsize=(12, nrows * 6), sharex=True, sharey=True) x = [-0.88, 0.88, 0.88, -0.88, -0.88] y = [1.51, 1.51, 3.4, 3.4, 1.51] # at_bat_number でグループ化 grouped_by_batter = df_660261_fujinami.groupby('at_bat_number') # グラフのタイトル用に結果データを取得 results_data = df_660261_2023_04_15_results_filtered_sorted # unique_batters を at_bat_number で並べ替え unique_batters = sorted(unique_batters, key=lambda x: grouped_by_batter.get_group(x).iloc[0]['at_bat_number']) for i, batter in enumerate(unique_batters): data_by_batter = grouped_by_batter.get_group(batter) ax = axs[i // ncols, i % ncols] ax.fill(x, y, color='r', alpha=0.1) grouped_by_pitch_type = data_by_batter.groupby('pitch_type') for pitch_type, data in grouped_by_pitch_type: ax.scatter(data['plate_x'], data['plate_z'], label=pitch_type, s=200) hit_data = data[data['events'].isin(['single', 'double', 'triple', 'home_run'])] if not hit_data.empty: ax.scatter(hit_data['plate_x'], hit_data['plate_z'], marker='x', s=100, label=f'Hit ({pitch_type})') for idx, row in data.iterrows(): ax.text(row['plate_x'], row['plate_z'], f"{row['pitch_number']}", fontsize=12, ha='center', va='center', color='white') last_pitch_result = results_data.iloc[i]['events'] ax.set_title(f'Batter {i+1} (Last Pitch: {last_pitch_result})') ax.set_xlim(-3, 3) ax.set_ylim(-2, 6) ax.set_xlabel('Plate X') ax.set_ylabel('Plate Z') ax.legend() ax.grid(which='both', linestyle='--', color='gray', alpha=0.5) plt.tight_layout() plt.show() 各打者との対戦結果(題名に対戦ID)import matplotlib.pyplot as plt # 2023年4月15日のデータをフィルタリング df_660261_fujinami = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-15'] unique_batters = sorted(df_660261_fujinami['at_bat_number'].unique()) nrows = (len(unique_batters) + 1) // 2 ncols = 2 fig, axs = plt.subplots(nrows, ncols, figsize=(12, nrows * 6), sharex=True, sharey=True) x = [-0.88, 0.88, 0.88, -0.88, -0.88] y = [1.51, 1.51, 3.4, 3.4, 1.51] # at_bat_number でグループ化 grouped_by_batter = df_660261_fujinami.groupby('at_bat_number') # グラフのタイトル用に結果データを取得 results_data = df_660261_2023_04_15_results_filtered_sorted[['batter', 'events', 'des']] # unique_batters を at_bat_number で並べ替え unique_batters = sorted(unique_batters, key=lambda x: grouped_by_batter.get_group(x).iloc[0]['at_bat_number']) for i, batter in enumerate(unique_batters): data_by_batter = grouped_by_batter.get_group(batter) ax = axs[i // ncols, i % ncols] ax.fill(x, y, color='r', alpha=0.1) grouped_by_pitch_type = data_by_batter.groupby('pitch_type') for pitch_type, data in grouped_by_pitch_type: ax.scatter(data['plate_x'], data['plate_z'], label=pitch_type, s=200) hit_data = data[data['events'].isin(['single', 'double', 'triple', 'home_run'])] if not hit_data.empty: ax.scatter(hit_data['plate_x'], hit_data['plate_z'], marker='x', s=100, label=f'Hit ({pitch_type})') for idx, row in data.iterrows(): ax.text(row['plate_x'], row['plate_z'], f"{row['pitch_number']}", fontsize=12, ha='center', va='center', color='white') last_pitch_result = results_data.iloc[i]['events'] # タイトルに表示する打者IDを取得 batter_id = results_data.iloc[i]['batter'] # イニングとアウトカウントを取得 inning = data_by_batter.iloc[0]['inning'] outs_when_up = data_by_batter.iloc[0]['outs_when_up'] # タイトルを設定 ax.set_title(f'Batter {batter_id}: Inning {inning}, Outs {outs_when_up} - {last_pitch_result}') ax.set_xlim(-3, 3) ax.set_ylim(-2, 6) ax.set_xlabel('Plate X') ax.set_ylabel('Plate Z') ax.legend() ax.grid(which='both', linestyle='--', color='gray', alpha=0.5) plt.tight_layout() plt.show() 各打者との対戦結果 / 文章des_list = df_660261_2023_04_15_results_filtered_sorted['des'].tolist() for des in des_list: print(des) 結果Brandon Nimmo strikes out swinging. Starling Marte flies out to left fielder Conner Capel. Francisco Lindor doubles (6) on a ground ball to right fielder Ramon Laureano. Pete Alonso strikes out swinging. Jeff McNeil flies out to center fielder Esteury Ruiz. Mark Canha strikes out swinging. Daniel Vogelbach grounds out, first baseman Jesus Aguilar to pitcher Shintaro Fujinami. Luis Guillorme strikes out swinging. Francisco Alvarez flies out to second baseman Tony Kemp. Brandon Nimmo singles on a line drive to right fielder Ramon Laureano. Starling Marte flies out sharply to center fielder Esteury Ruiz. Francisco Lindor grounds out, second baseman Tony Kemp to first baseman Jesus Aguilar. Pete Alonso homers (7) on a fly ball to left field. Jeff McNeil grounds out to first baseman Jesus Aguilar. Mark Canha flies out sharply to center fielder Esteury Ruiz. Daniel Vogelbach grounds out, third baseman Jace Peterson to first baseman Jesus Aguilar. Luis Guillorme walks. Francisco Alvarez strikes out on a foul tip. Brandon Nimmo lines out sharply to right fielder Ramon Laureano. Starling Marte hit by pitch. Francisco Lindor grounds out, second baseman Tony Kemp to first baseman Jesus Aguilar. Starling Marte to 3rd. Pete Alonso grounds out, shortstop Aledmys Diaz to first baseman Jesus Aguilar. Jeff McNeil grounds out, first baseman Jesus Aguilar to pitcher Shintaro Fujinami. Mark Canha homers (2) on a fly ball to left field. Daniel Vogelbach walks. 各打者との対戦結果 / 文章 ※並び替えdes_list = df_660261_2023_04_15_results_filtered_sorted['des'].tolist() for i, des in enumerate(des_list, 1): print(f"{i}. {des}") 結果1. Brandon Nimmo strikes out swinging. 2. Starling Marte flies out to left fielder Conner Capel. 3. Francisco Lindor doubles (6) on a ground ball to right fielder Ramon Laureano. 4. Pete Alonso strikes out swinging. 5. Jeff McNeil flies out to center fielder Esteury Ruiz. 6. Mark Canha strikes out swinging. 7. Daniel Vogelbach grounds out, first baseman Jesus Aguilar to pitcher Shintaro Fujinami. 8. Luis Guillorme strikes out swinging. 9. Francisco Alvarez flies out to second baseman Tony Kemp. 10. Brandon Nimmo singles on a line drive to right fielder Ramon Laureano. 11. Starling Marte flies out sharply to center fielder Esteury Ruiz. 12. Francisco Lindor grounds out, second baseman Tony Kemp to first baseman Jesus Aguilar. 13. Pete Alonso homers (7) on a fly ball to left field. 14. Jeff McNeil grounds out to first baseman Jesus Aguilar. 15. Mark Canha flies out sharply to center fielder Esteury Ruiz. 16. Daniel Vogelbach grounds out, third baseman Jace Peterson to first baseman Jesus Aguilar. 17. Luis Guillorme walks. 18. Francisco Alvarez strikes out on a foul tip. 19. Brandon Nimmo lines out sharply to right fielder Ramon Laureano. 20. Starling Marte hit by pitch. 21. Francisco Lindor grounds out, second baseman Tony Kemp to first baseman Jesus Aguilar. Starling Marte to 3rd. 22. Pete Alonso grounds out, shortstop Aledmys Diaz to first baseman Jesus Aguilar. 23. Jeff McNeil grounds out, first baseman Jesus Aguilar to pitcher Shintaro Fujinami. 24. Mark Canha homers (2) on a fly ball to left field. 25. Daniel Vogelbach walks. ブランドン・ニモが空振り三振。スターリング・マルテが左翼手コナー・ケーペルへのフライアウト。フランシスコ・リンドーアがライトフィールダー・ラモン・ローレアノへのグラウンドボールで二塁打(6)。ピート・アロンソが空振り三振。ジェフ・マクニールが中堅手エステュリ・ルイスへのフライアウト。マーク・カナが空振り三振。ダニエル・ヴォーゲルバックが一塁手ジーザス・アギラーから投手藤浪晋太郎へのゴロアウト。ルイス・ギリオルメが空振り三振。フランシスコ・アルバレスが二塁手トニー・ケンプへのフライアウト。ブランドン・ニモがライトフィールダー・ラモン・ローレアノへのライナーシングル。スターリング・マルテが中堅手エステュリ・ルイスへの鋭いフライアウト。フランシスコ・リンドーアが二塁手トニー・ケンプから一塁手ジーザス・アギラーへのゴロアウト。ピート・アロンソが左翼への本塁打(7)。ジェフ・マクニールが一塁手ジーザス・アギラーへのゴロアウト。マーク・カナが中堅手エステュリ・ルイスへの鋭いフライアウト。ダニエル・ヴォーゲルバックが三塁手ジェイス・ピーターソンから一塁手ジーザス・アギラーへのゴロアウト。ルイス・ギリオルメが四球。フランシスコ・アルバレスがファウルチップで三振。ブランドン・ニモがライトフィールダー・ラモン・ローレアノへの鋭いライナーアウト。スターリング・マルテが死球。フランシスコ・リンドーアが二塁手トニー・ケンプから一塁手ジーザス・アギラーへのゴロアウト。スターリング・マルテが3塁へ進む。ピート・アロンソが遊撃手アレドミス・ディアスから一塁手ジーザス・アギラーへのゴロアウト。ジェフ・マクニールが一塁手ジーザス・アギラーから投手藤浪晋太郎へのゴロアウト。マーク・カナが左翼への本塁打(2)。ダニエル・ヴォーゲルバックが四球。対戦打者ID# 2023年4月15日のデータをフィルタリング df_660261_fujinami = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-15'] unique_batters = sorted(df_660261_fujinami['at_bat_number'].unique()) # at_bat_number でグループ化 grouped_by_batter = df_660261_fujinami.groupby('at_bat_number') # グラフのタイトル用に結果データを取得 results_data = df_660261_2023_04_15_results_filtered_sorted[['batter', 'events', 'des']] # unique_batters を at_bat_number で並べ替え unique_batters = sorted(unique_batters, key=lambda x: grouped_by_batter.get_group(x).iloc[0]['at_bat_number']) # バッターIDを格納するリスト batter_ids = [] # 各バッターのIDをリストに追加 for i, batter in enumerate(unique_batters): batter_id = results_data.iloc[i]['batter'] batter_ids.append(batter_id) print(batter_ids) 結果[607043, 516782, 596019, 624413, 643446, 592192, 596129, 641645, 682626, 607043, 516782, 596019, 624413, 643446, 592192, 596129, 641645, 682626, 607043, 516782, 596019, 624413, 643446, 592192, 596129] 対戦打者ID - 名前の紐づけfrom pybaseball import playerid_reverse_lookup # バッターIDのリスト batter_ids = [607043, 516782, 596019, 624413, 643446, 592192, 596129, 641645, 682626, 607043, 516782, 596019, 624413, 643446, 592192, 596129, 641645, 682626, 607043, 516782, 596019, 624413, 643446, 592192, 596129] # 重複を削除する unique_batter_ids = list(set(batter_ids)) # バッターIDと名前の対応関係を格納する辞書 batter_names = {} # IDごとに選手名を検索 for batter_id in unique_batter_ids: player_info = playerid_reverse_lookup([batter_id], key_type='mlbam') batter_name = player_info['name_first'].iloc[0] + ' ' + player_info['name_last'].iloc[0] batter_names[batter_id] = batter_name # バッターIDと名前の対応関係を表示 for batter_id, batter_name in batter_names.items(): print(f'{batter_id}: {batter_name}') 結果Gathering player lookup table. This may take a moment. 592192: mark canha 596129: dan vogelbach 682626: francisco álvarez 607043: brandon nimmo 641645: luis guillorme 516782: starling marte 596019: francisco lindor 643446: jeff mcneil 624413: pete alonso 各対戦打者との結果 (題名に名前入り)import matplotlib.pyplot as plt # ID と選手名のマッピング id_to_name_mapping = { 592192: "Mark Canha", 596129: "Dan Vogelbach", 682626: "Francisco Álvarez", 607043: "Brandon Nimmo", 641645: "Luis Guillorme", 516782: "Starling Marte", 596019: "Francisco Lindor", 643446: "Jeff McNeil", 624413: "Pete Alonso" } # 2023年4月15日のデータをフィルタリング df_660261_fujinami = df_660261_all_dates[df_660261_all_dates['game_date'] == '2023-04-15'] unique_batters = sorted(df_660261_fujinami['at_bat_number'].unique()) nrows = (len(unique_batters) + 1) // 2 ncols = 2 fig, axs = plt.subplots(nrows, ncols, figsize=(12, nrows * 6), sharex=True, sharey=True) x = [-0.88, 0.88, 0.88, -0.88, -0.88] y = [1.51, 1.51, 3.4, 3.4, 1.51] # at_bat_number でグループ化 grouped_by_batter = df_660261_fujinami.groupby('at_bat_number') # グラフのタイトル用に結果データを取得 results_data = df_660261_2023_04_15_results_filtered_sorted[['batter', 'events', 'des']] # unique_batters を at_bat_number で並べ替え unique_batters = sorted(unique_batters, key=lambda x: grouped_by_batter.get_group(x).iloc[0]['at_bat_number']) for i, batter in enumerate(unique_batters): data_by_batter = grouped_by_batter.get_group(batter) ax = axs[i // ncols, i % ncols] ax.fill(x, y, color='r', alpha=0.1) grouped_by_pitch_type = data_by_batter.groupby('pitch_type') for pitch_type, data in grouped_by_pitch_type: ax.scatter(data['plate_x'], data['plate_z'], label=pitch_type, s=200) hit_data = data[data['events'].isin(['single', 'double', 'triple', 'home_run'])] if not hit_data.empty: ax.scatter(hit_data['plate_x'], hit_data['plate_z'], marker='x', s=100, label=f'Hit ({pitch_type})') for idx, row in data.iterrows(): ax.text(row['plate_x'], row['plate_z'], f"{row['pitch_number']}", fontsize=12, ha='center', va='center', color='white') last_pitch_result = results_data.iloc[i]['events'] # タイトルに表示する打者名を取得 batter_id = results_data.iloc[i]['batter'] batter_name = id_to_name_mapping[batter_id] # イニングとアウトカウントを取得 inning = data_by_batter.iloc[0]['inning'] outs_when_up = data_by_batter.iloc[0]['outs_when_up'] # タイトルを設定 ax.set_title(f'{batter_name} : Inning {inning}, Outs {outs_when_up} - {last_pitch_result}') ax.set_xlim(-3, 3) ax.set_ylim(-2, 6) ax.set_xlabel('Plate X') ax.set_ylabel('Plate Z') ax.legend() ax.grid(which='both', linestyle='--', color='gray', alpha=0.5) plt.tight_layout() plt.show() 以上 ## Publication Information - [Shogaku](https://paragraph.com/@shogaku/): Publication homepage - [All Posts](https://paragraph.com/@shogaku/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@shogaku): Subscribe to updates - [Twitter](https://twitter.com/ussu_ussu_ussu): Follow on Twitter