今年の大谷翔平選手のホームランペースはどうなの?AIと作るグラフアプリ

Python

2025年も好調なスタートをきった大谷翔平選手。

毎試合の活躍が楽しみですね!

4月17日時点で、すでに6本のホームランを放っています。

現在20試合を終えたところですが、このホームランペースは、過去と比べてどうなのでしょうか?

54本を打ち、ホームラン王に輝いた2024年と比べて、速いのでしょうか?それとも遅いのでしょうか?

気になったので、2023年、2024年のデータと比較して、グラフで見てみたいと思います。

「プログラミングは難しそう…」もしあなたがそう思っているなら、AIにお願いすれば簡単に作ってくれます。

ただし、プロンプト(指示)を的確にできればですが…

大谷翔平選手のホームラン数の推移を、この記事で、最終的に仕上げたPythonコードで表示したアニメーションです。

試合ごとにホームラン数が伸びていく様子が、うまく表現されているのではないでしょうか。

これを見ると、2024年以上に良いペースでホームランを打っているのがわかりますね。

この記事では、AIに手伝ってもらいながら、目的のグラフを作った過程を、ステップバイステップでご紹介します。

まずはAIにお願い!大谷選手のホームランペースをグラフ化!

「プログラミング?コード?難しそう?」という方も、ご安心ください。この記事では、コードを一行も書かずに、AIに指示を出すだけでグラフを作成します。

今回使用するのは、Google Gemini のCanvasというAIツール。Gemini Canvasは、まるで絵を描くように、あなたのイメージを伝えることができる、魔法のようなツールです。

Gemini Canvasについては以下の記事で解説していますので、良かったらご覧ください。

今回の目標は、Gemini Canvasに、大谷翔平選手のホームランペースをグラフ化してもらうこと。

大谷選手の打撃成績は以下のサイトを参照します。

Shohei Ohtani Game Logs

まずは、最初のステップとして、3年分のホームランの累計グラフを表示するPythonコードを作成してもらいます。

以下のようなお願いをしてみました。

https://sample-d6924.web.app/public/mlblog.html
に、各年の試合ごとの打撃成績が表で載っています。表は3つあって、一番上が2023年、真ん中が2024年、一番下が2025年のデータです。
この表から、それぞれの年のホームランの数を順番に足していって(累計ホームラン数)、それを試合数ごとに線でつないだグラフを3本作ってほしいです。
グラフの種類: 折れ線グラフ
線の数: 3本(2023年、2024年、2025年それぞれのデータ)
横軸: 試合数(表の中の「No」という列の数字を使ってください)
縦軸: ホームラン数(表の中の「HR」という列の数字を、その年の最初の試合から順番に足していった数を使ってください)
実行環境: Google Colaboratory(Colab)で動かせるPythonのコードでお願いします。

最初に作ってくれたコードは、残念ながら期待通りに動いてくれませんでした。

ここで、少しずつ確認しながら、改善していっても良いのですが、今回は以下のようにお願いしました。

「アプローチを変えて、他の方法で作ってください」

すると、AIは最初のシンプルなグラフを作成してくれたのです。

もっとカッコよくならない?AIにデザインの改良をお願い!

AIが作った最初のグラフは、まだちょっとシンプルかもしれません。

でも、心配ご無用。Gemini Canvasを使えば、デザインの修正も簡単です。

グラフのデザインをもっとクールな感じにしてください。
線はもっと太く、ギザギザも気になるので、滑らかになるようにしてください。

すると、要望通り(?)にグラフのデザインを変更してくれました。

ひとまず、このあたりで良しとしましょう!

仕上げの一押し!アニメーションでグラフをさらに魅力的に!

現状のグラフでも十分なのですが、動きがあったら、もっと 印象的 だと思いませんか?

そこでさらに、次のようなお願いをしました。

グラフにアニメーションを追加してください。
試合が進むにつれて、ホームランの累積数が増えていく様子がわかるようにしたいです。
あと、アニメーションの途中で、現在のホームラン数を表示してください。

何度か、正確にイメージを伝えるため、AIと会話しながら出来上がったのが上の動画のグラフです。

ちょっと寄り道:作成したコードを覗いてみよう!

「AIに指示するだけで、こんなに面白いグラフが作れるなんて、まるで魔法みたい!」

そう思った方もいるかもしれません。でも、実はこの魔法の裏側には、Pythonというプログラミング言語の力が 隠されている んです。

作成されたコードは、この記事の最後に掲載しています。興味のある方は覗いてみましょう。

今回のグラフ作成を支えた立役者たち:Pythonライブラリの紹介

Pythonは、世界中で広く使われているプログラミング言語で、データ分析や機械学習の分野で特に強力な力を発揮します。

今回のグラフ作成では、主に以下のPythonライブラリ(便利な道具箱のようなもの)が使われました。

ライブラリを使うと、自分で複雑な処理を細かく書かなくても、データの取得やグラフの描画、アニメーションの追加などが簡単にできます。

requests: ウェブからデータを取得する処理を行う

requestsは、Pythonでウェブサイトにアクセスし、データを取得するためのライブラリです。

今回の例では、大谷選手のホームラン数のデータを掲載しているウェブサイトから、このライブラリを使ってデータを取得しました。

BeautifulSoup: HTMLで書かれたウェブページの情報を解析

ウェブサイトのデータは、HTMLという言語で書かれています。

BeautifulSoupは、このHTMLを解析し、必要な情報を抽出するためのライブラリです。

今回の例では、requestsで取得したHTMLから、大谷選手のホームラン数のデータを抽出するために使用しました。

matplotlib.pyplot: 取得したデータをグラフで表現

matplotlib.pyplotは、Pythonでグラフを描画するためのライブラリです。

折れ線グラフや棒グラフなど、様々な種類のグラフを、美しいデザインで作成することができます。

今回の例では、BeautifulSoupで抽出したデータをもとに、大谷選手のホームラン数のグラフを描画するために使用しました。

もっと深く探求したい方へ

今回の体験で、「プログラミングって、意外と面白いかも?」と感じた方もいるのではないでしょうか。

もしそうなら、ぜひ次のステップへ進んでみてください。

AIにお願いすれば、ある程度のプログラムを作ってくれます。

しかしプログラミングを体系的に学ぶことは、あなたのアイデアを形にするための 強力な武器 になります。

今回の場合も、具体的なライブラリを指定してAIにお願いすれば、イメージにあったものを作ってもらう早道になったと思われます。

「でも、どうやって勉強すればいいの?」「独学でも大丈夫?」

以下にどういった学習手段があるかの記事を書きましたので、ぜひご覧ください。

まとめ

今回は、AIの力を借りて、 動きのあるグラフが作れることを体験しました。

この記事を通して、AIがプログラミングの新しい可能性を切りひらいていることを感じていただけたでしょうか。

プログラミングを学ぶことで、AIともっと深く連携し、より高度なデータ分析や表現が可能になります。

他にも、様々なアレンジが可能だと思います。

ぜひチャレンジしてみてください。

最後に、今回作成したPythonコードを掲載しておきます。

なお、Colabでコード実行前に、以下のコマンドをコード欄に張り付けて実行しておくことが必要です。

!pip install japanize-matplotlib
import pandas as pd
import japanize_matplotlib
import matplotlib.pyplot as plt
import requests
from bs4 import BeautifulSoup
import re
import numpy as np
import matplotlib.patheffects as path_effects
import matplotlib.animation as animation
from IPython.display import HTML, display

def extract_table_data(table):
    """
    Beautiful SoupのTable要素からデータを抽出する関数。

    Args:
        table (bs4.element.Tag): HTMLのtable要素。

    Returns:
        pandas.DataFrame: 抽出されたデータを含むDataFrame。
                        列名はテーブルのヘッダーから取得し、
                        数値データは整数に変換。
    """
    headers = [th.text.strip() for th in table.find_all('th')]
    rows = []
    for tr in table.find_all('tr')[1:]:  # ヘッダー行をスキップ
        cols = [td.text.strip() for td in tr.find_all('td')]
        if cols:  # 空の行でないことを確認
            rows.append(cols)

    df = pd.DataFrame(rows, columns=headers[:len(cols)]) # ヘッダーの数を列数に合わせる

    # 数値データへの変換を試みる
    for col in df.columns:
        # 'No'列は大抵の場合数値
        if col == 'No':
            df[col] = pd.to_numeric(df[col], errors='coerce')
        # 'HR'列も数値に変換
        elif col == 'HR':
            df[col] = pd.to_numeric(df[col], errors='coerce')
        # 数値変換に失敗した場合はNaNにする
        else:
            df[col] = df[col].apply(lambda x: pd.to_numeric(x, errors='coerce') if re.match(r'^\d+(\.\d+)?$', x) else x)
    return df

def plot_cumulative_homerun_trends(df_2023, df_2024, df_2025):
    """
    3年間のホームラン数の累積推移を折れ線グラフで表示する関数。
    データを補間して滑らかな曲線を描画し、アニメーションも追加。

    Args:
        df_2023 (pandas.DataFrame): 2023年のデータを含むDataFrame。
        df_2024 (pandas.DataFrame): 2024年のデータを含むDataFrame。
        df_2025 (pandas.DataFrame): 2025年のデータを含むDataFrame。
    """
    fig, ax = plt.subplots(figsize=(12, 8))
    ax.set_facecolor('#222222')

    years = [2023, 2024, 2025]
    dfs = [df_2023, df_2024, df_2025]
    labels = ['2023年', '2024年', '2025年']
    colors = ['magenta', 'aqua', 'lime']
    lines = []
    x_smooth_vals = []
    y_smooth_vals = []
    max_no = 0
    max_frames = 0
    frames = []
    texts = []

    for i, df in enumerate(dfs):
        if 'No' in df and 'HR' in df:
            x = df['No'].values
            y = df['HR'].values
            max_no = max(max_no, x.max())
            frames.append(len(x))
            max_frames = max(max_frames, len(x))
            if len(x) > 1:
                x_smooth = x
                y_smooth = np.cumsum(y)
                x_smooth_vals.append(x_smooth)
                y_smooth_vals.append(y_smooth)
                line, = ax.plot([], [], lw=4, color=colors[i], label=labels[i])
                lines.append(line)
                text = ax.text(0, 0, '', fontsize=18, color=colors[i], fontweight='bold', ha='left', va='bottom')
                texts.append(text)
            else:
                line, = ax.plot(x, np.cumsum(y), marker='o', color=colors[i], label=labels[i], lw=4)
                lines.append(line)
                x_smooth_vals.append(x)
                y_smooth_vals.append(np.cumsum(y))
                text = ax.text(0, 0, '', fontsize=18, color=colors[i], fontweight='bold', ha='left', va='bottom')
                texts.append(text)
        else:
            print(f"{labels[i]}のデータには'No'または'HR'列が含まれていません。")
            lines.append(None)
            x_smooth_vals.append([])
            y_smooth_vals.append([])
            texts.append(None)

    ax.set_xlabel('試合数', fontsize=14, color='black')
    ax.set_ylabel('ホームラン数 (累計)', fontsize=14, color='black')
    plt.rcParams['font.family'] = 'IPAPGothic'
    japanize_matplotlib.japanize()
    ax.set_title('年別ホームラン数累計推移', fontsize=16, color='black')
    ax.legend(fontsize=12, loc='upper left', facecolor='#444444', edgecolor='white', labelcolor='white')
    ax.grid(True, linestyle='--', alpha=0.7, color='gray')
    ax.set_xlim(0, max_no + 10)  # 横軸の最大値を10増やす
    ax.set_ylim(0, max(y_smooth_vals[0].max(), y_smooth_vals[1].max(), y_smooth_vals[2].max()) * 1.1)
    ax.tick_params(axis='both', which='major', labelsize=12, color='black', labelcolor='black')

    def update(frame):
        for i, line in enumerate(lines):
            if line is not None and len(x_smooth_vals[i]) > 1:
                length = int(len(x_smooth_vals[i]) * (frame / frames[i]))
                length = min(length, len(x_smooth_vals[i]) - 1)
                line.set_data(x_smooth_vals[i][:length+1], y_smooth_vals[i][:length+1])
                line.set_path_effects([path_effects.SimpleLineShadow(), path_effects.Normal()])
                # テキストの更新
                x_val = x_smooth_vals[i][length]
                y_val = y_smooth_vals[i][length]
                texts[i].set_position((x_val, y_val))
                texts[i].set_text(f'{y_val:.0f}本')
                texts[i].set_color(colors[i])
            elif line is not None:
                length = int(len(x_smooth_vals[i]) * (frame / frames[i]))
                length = min(length, len(x_smooth_vals[i]) - 1)
                line.set_data(x_smooth_vals[i][:length+1], y_smooth_vals[i][:length+1])
                line.set_path_effects([path_effects.SimpleLineShadow(), path_effects.Normal()])
                # テキストの更新
                x_val = x_smooth_vals[i][length]
                y_val = y_smooth_vals[i][length]
                texts[i].set_position((x_val, y_val))
                texts[i].set_text(f'{y_val:.0f}本')
                texts[i].set_color(colors[i])
            else:
                pass
        return lines + texts

    ani = animation.FuncAnimation(fig, update, frames=max_frames, interval=100)
    plt.close()
    return HTML(ani.to_jshtml())

def main():
    """
    メイン関数。Webページからデータを取得し、グラフを生成する。
    """
    url = "https://sample-d6924.web.app/public/mlblog.html"
    response = requests.get(url)
    response.raise_for_status()
    soup = BeautifulSoup(response.content, 'html.parser')

    tables = soup.find_all('table')
    if len(tables) < 3:
        print("必要なテーブルが見つかりませんでした。HTML構造が変更された可能性があります。")
        return

    df_2023 = extract_table_data(tables[0])
    df_2024 = extract_table_data(tables[1])
    df_2025 = extract_table_data(tables[2])

    html_animation = plot_cumulative_homerun_trends(df_2023, df_2024, df_2025)
    display(html_animation)
    return

if __name__ == "__main__":
    main()

コメント

タイトルとURLをコピーしました