NBAデータをJSON形式で取得して分析するPythonスクリプト

## はじめに

NBAの試合データを取得し、分析するためのスクリプトを作成しました。このスクリプトでは、`nba_api`を使って特定のチームの試合データを取得し、チーム全体の統計や個人のパフォーマンスを**JSON形式**で保存します。

JSON形式で保存する理由は、ChatGPTなどのAIツールを活用して効率的にデータを分析できるようにするためです。この記事では、スクリプトの使い方や生成されたJSONデータをChatGPTで考察するためのプロンプト例も紹介します。

## 使用するライブラリ

このスクリプトでは以下のライブラリを使用しています：

- `nba_api`: NBAの公式データを取得するためのAPIクライアント
- `pandas`: データフレーム形式でデータを処理するため
- `json`: データをJSON形式で保存するため
- `numpy`: 欠損値処理のサポート

ライブラリがインストールされていない場合は、以下のコマンドを使ってインストールしてください：

```bash
pip install nba_api pandas numpy
```

## スクリプト

``` Python
import os
import time
import json
import pandas as pd
from nba_api.stats.static import teams
from nba_api.stats.endpoints import leaguegamefinder, boxscoretraditionalv2
from requests.exceptions import ReadTimeout
import numpy as np

def fetch_team_data_to_json(team_name="Los Angeles Lakers", season="2023-24"):
    # チームIDの取得
    nba_teams = teams.get_teams()
    team_id = None
    team_abbreviation = None
    for team in nba_teams:
        if team['full_name'] == team_name:
            team_id = team['id']
            team_abbreviation = team['abbreviation']
            break

    if team_id is None:
        print(f"Team '{team_name}' not found.")
        return

    filename = f"{team_name.replace(' ', '_')}_{season}_NBA_Game_Data.json"
    gamefinder = leaguegamefinder.LeagueGameFinder(season_nullable=season, team_id_nullable=team_id)
    games = gamefinder.get_data_frames()[0]
    data = []
    team_stat_list = []

    for index, game in games.iterrows():
        game_id = game["GAME_ID"]
        game_date = game["GAME_DATE"]
        matchup = game["MATCHUP"]

        attempts = 3
        while attempts > 0:
            try:
                boxscore = boxscoretraditionalv2.BoxScoreTraditionalV2(game_id=game_id)
                team_stats = boxscore.get_data_frames()[1]
                player_stats = boxscore.get_data_frames()[0]
                break
            except ReadTimeout:
                print(f"Timeout for game {matchup} on {game_date}. Retrying...")
                attempts -= 1
                time.sleep(5)
            except Exception as e:
                print(f"Failed to retrieve data for game {matchup} on {game_date}. Error: {e}")
                break
            
        if attempts == 0:
            continue

        team_stats_row = team_stats[team_stats["TEAM_ABBREVIATION"] == team_abbreviation].iloc[0]
        def safe_int(value, default=0):
            return int(value) if not pd.isna(value) else default
        def safe_float(value, default=0.0):
            return float(value) if not pd.isna(value) else default
        
        team_stat = {
            "game_date": game_date,
            "matchup": matchup,
            "points": safe_int(team_stats_row["PTS"]),
            "field_goal_percentage": safe_float(team_stats_row["FG_PCT"]),
            "three_point_percentage": safe_float(team_stats_row["FG3_PCT"]),
            ...
        }
        team_stat_list.append(team_stat)

        player_stats_team = player_stats[player_stats["TEAM_ABBREVIATION"] == team_abbreviation]
        players_data = []
        for _, row in player_stats_team.iterrows():
            players_data.append({
                "player_name": row["PLAYER_NAME"],
                ...
            })

        data.append({
            "game_date": game_date,
            "matchup": matchup,
            "team_stats": team_stat,
            "player_stats": players_data
        })

        print(f"Processed data for game {matchup} on {game_date}")
        time.sleep(5)

    team_stats_df = pd.DataFrame(team_stat_list)
    team_performance_summary = {
        ...
    }

    output_data = {
        "team_performance_summary": team_performance_summary,
        "games": data
    }

    with open(filename, "w", encoding="utf-8") as f:
        json.dump(output_data, f, ensure_ascii=False, indent=4)
    print(f"All game data for {team_name} saved to {filename}")

fetch_team_data_to_json(team_name="Los Angeles Lakers", season="2023-24")
```

## スクリプトの機能

### 1. 特定のチームのデータ取得

指定したチームの全試合データを取得し、JSON形式で保存します。以下のようにチーム名とシーズンを指定して利用します：

```python
fetch_team_data_to_json(team_name="Los Angeles Lakers", season="2023-24")
```

### 2. JSON形式での保存

取得したデータは次のような構造で保存されます：

- `team_performance_summary`: チーム全体の平均パフォーマンス（得点、リバウンド、アシストなど）
- `games`: 各試合の詳細データ（チーム統計と個人統計）

JSONファイルの内容例：

```json
{
    "team_performance_summary": {
        "average_points": 115.2,
        "average_field_goal_percentage": 48.3,
        "average_three_point_percentage": 35.7,
        "average_free_throw_percentage": 78.2,
        "average_rebounds": 44.1,
        "average_assists": 25.8,
        "average_turnovers": 13.5,
        "average_steals": 7.8,
        "average_blocks": 4.2,
        "average_plus_minus": 2.5
    },
    "games": [
        {
            "game_date": "2023-10-25",
            "matchup": "LAL vs DEN",
            "team_stats": {
                "points": 118,
                "field_goal_percentage": 47.8,
                "three_point_percentage": 36.5,
                "free_throw_percentage": 82.1,
                "rebounds": 45,
                "assists": 26,
                "turnovers": 14,
                "steals": 8,
                "blocks": 3,
                "plus_minus": -5
            },
            "player_stats": [
                {
                    "player_name": "LeBron James",
                    "minutes": "35:12",
                    "points": 28,
                    "rebounds": 8,
                    "assists": 10,
                    "steals": 1,
                    "blocks": 0,
                    "turnovers": 3,
                    "field_goals": "10/20 (50.0%)",
                    "three_points": "2/5 (40.0%)"
                },
                ...
            ]
        },
        ...
    ]
}
```

---

## JSONデータをChatGPTで活用する

JSON形式で保存したデータは、ChatGPTに考察を依頼するために最適な形式です。以下のプロンプトを使用することで、ChatGPTに効率的に分析を依頼できます。

### プロンプト例

#### チームのパフォーマンスを分析する場合
```plaintext
以下のJSON形式のデータを分析して、チーム全体のパフォーマンスを考察してください。このデータは特定のNBAチームの試合データを含んでいます。特に、得点、リバウンド、アシスト、ターンオーバー、スティール、ブロック、シュート成功率などの統計を比較して、勝利や敗北の要因についてコメントしてください。

データ:
<ここにJSONデータを貼り付ける>
```

ChatGPT 回答

```
レイカーズの選手のパフォーマンスを試合ごとに分析した結果を表示しました。このデータには、得点、アシスト、リバウンド、スティール、ターンオーバーの平均値が含まれています。

### 考察
考察
高い貢献度の選手:

レブロン・ジェームズ:
- 平均24.1得点、7.8アシスト、6.9リバウンドと攻守ともに非常に高い貢献度を示しています。
- ターンオーバーがやや多い傾向があり、ここを改善できればさらに効率的なプレーが期待されます。

アンソニー・デイビス:
- 平均23.3得点、11.9リバウンドでリバウンド面ではチームトップの活躍です。
- 安定感のある得点力とディフェンス力が勝利に直結しています。

ディアンジェロ・ラッセル:
- 平均16.7得点、5.9アシストとプレーメーカーとしても機能しています。
- ディフェンス（スティール）での貢献は控えめですが、オフェンスにおける安定性は高いです。

オースティン・リーブス:
- 平均15.7得点、5.2アシストとサポートスコアラーとして機能。
- ターンオーバーがやや多いものの、安定した得点力を発揮しています。

改善が必要な選手または分野:

八村塁:
- 平均12.5得点と安定した貢献を見せていますが、アシスト（平均1.1）やスティール（0.5）での貢献度が低いです。
- リバウンドやディフェンス面での存在感をさらに向上させることで、チーム全体への貢献度を高めることが求められます。

ターンオーバーの抑制:
- 特にレブロン・ジェームズやディアンジェロ・ラッセルはターンオーバー数が平均よりやや多い傾向があります。
- ゲームメイクを効率化することで、より安定した試合運びが可能になるでしょう。

これらの結果を基に、個々の選手の役割を強化し、チーム全体の効率を高めることが重要です
```

## まとめ

このスクリプトを使えば、NBAの試合データをJSON形式で取得し、ChatGPTを活用して効率的に分析できます。JSON形式のデータは柔軟性が高く、ChatGPTに読み込ませることで、試合結果や選手のパフォーマンスについて高度な洞察を得られます。日本のB-LeagueもデータやAPIを公開していって欲しいですね。

---

記事が面白かったらコーヒー奢ってください！
https://buymeacoffee.com/takurot