0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【NBAシリーズ】今シーズンの八村塁は一味違う - ①データ取得編

0
Last updated at Posted at 2025-12-01

1. はじめに

僕はNBAが好きだ。BLACK SAMURAI こと Rui Hachimura が好きだ。

2024-25シーズンから本格的に観戦を始めた新参者ではあるが、ロサンゼルスレイカーズ(LAL)を応援している。
後述するが、今シーズンの Rui は執筆時点(2025/12/2)で、3Pシュートの成功率がNBA全体で6位であり、ミッドレンジシュートもかなりの確率で決めることから、解説も思わずMidrange 99と言っちゃうほどである$^{*1}$。

データサイエンティストとして、NBA.com のデータを取得・分析・可視化し、日本の誇るBLACK SAMURAIのすごさをわからせる。それがこの連載シリーズの1つの目的である。

本シリーズは以下の3部構成をとる。
①データ取得編(今回):nba_api を使用してNBA.com のデータを取得する方法の備忘録
②データ分析編:①で取得したデータを分析してみる
③データ可視化編:①②を踏まえて、カッチョ良く可視化してみる

2. データ取得

※ 以下のPythonの実行はmarimo を使用している。
※ 今回は主に polars, nba_api を使用する

2.1 基本的なデータ

2.1.1 チーム情報

import polars as pl
from nba_api.stats.static import teams
all_teams_df = pl.DataFrame(teams.get_teams())
all_teams_df

001_0001.png

2.1.2 Active な選手一覧

import polars as pl
from nba_api.stats.static import players

all_players_df = pl.DataFrame(players.get_active_players())
all_players_df

001_0002.png

2.1.3 チームの試合情報

from nba_api.stats.endpoints import leaguegamefinder

# チームの全試合の情報を取得
gamefinder = leaguegamefinder.LeagueGameFinder(
    season_nullable='2025-26' # シーズン指定
)

games_df = pl.from_pandas(gamefinder.get_data_frames()[0])
games_df

001_0003.png

2.1.4 リーグのStatsリーダー

特定の選手の特定のStatsがリーグで何番目であるかを特定するのに使えそう。

league_leaders = leagueleaders.LeagueLeaders(season='2025-26')
league_leaders_df = pl.from_pandas(league_leaders.get_data_frames()[0])
league_leaders_df

001_0004.png

ちなみに、我らが Rui Hachimura の2025/12/2時点での3ポイント確率における順位$^{*2}$は

league_leaders_df.join(
    # チームの消化試合数を計算して結合
    games_df.group_by("TEAM_ABBREVIATION").agg(pl.len().alias("消化試合数")).rename({"TEAM_ABBREVIATION": "TEAM"}),
    on="TEAM",
    how="left"
).filter(
    # NBAのStatsでは、3ポイント成功数が消化試合数以上の選手のみを対象としている
    pl.col("FG3M") >= pl.col("消化試合数")
).sort(
    # 3ポイント成功率で降順ソート
    "FG3_PCT", descending=True
)

001_0005.png

このように6位にいることがわかる(すごすぎる)。

このようにnba_apiを使用すれば簡単にNBAのデータが手に入る。

3. 個人のデータ

もっとdeepなデータも取得できる。

こちらにずらっと nba_api で対応している Endpoints がまとめてあるのだが、その中でも今回はシュートに関するデータを取得する。

まずは、LALのチームIDと、Ruiの選手IDを取得する。

# LALのチームIDを特定
lakers = teams.find_team_by_abbreviation("LAL")
team_id = lakers['id']

# Ruiの選手IDを特定
rui = players.find_players_by_last_name("Hachimura")[0]
player_id = rui['id']

team_id, player_id
Output:
[
  1610612747,
  1629060
]

次は、チームIDと選手IDを元にデータを取得する。
今回は 2024-25のレギュラーシーズン/プレイオフのデータ、そして現在進行中の2025-26のレギュラーシーズンに絞って取得している。

import time
from nba_api.stats.endpoints import shotchartdetail

# 2023-24 のレギュラーシーズンのデータを取得
regular_season_2023_24 = pl.from_pandas(
    shotchartdetail.ShotChartDetail(
        team_id=team_id,
        player_id=player_id,
        season_type_all_star='Regular Season',
        season_nullable='2023-24',
        context_measure_simple='FGA',
    ).get_data_frames()[0]
)

time.sleep(1)  # APIの呼び出し間隔を空ける

# 2024-25 のレギュラーシーズンのデータを取得
regular_season_2024_25 = pl.from_pandas(
    shotchartdetail.ShotChartDetail(
        team_id=team_id,
        player_id=player_id,
        season_type_all_star='Regular Season',
        season_nullable='2024-25',
        context_measure_simple='FGA',
    ).get_data_frames()[0]
)

time.sleep(1)

# 2025-26 のレギュラーシーズンのデータを取得
regular_season_2025_26 = pl.from_pandas(
    shotchartdetail.ShotChartDetail(
        team_id=team_id,
        player_id=player_id,
        season_type_all_star='Regular Season',
        season_nullable='2025-26',
        context_measure_simple='FGA',
    ).get_data_frames()[0]
)

time.sleep(1)

# 2023-24 のプレイオフのデータを取得
playoff_2023_24 = pl.from_pandas(
    shotchartdetail.ShotChartDetail(
        team_id=team_id,
        player_id=player_id,
        season_type_all_star='Playoffs',
        season_nullable='2023-24',
        context_measure_simple='FGA',
    ).get_data_frames()[0]
)

time.sleep(1)

# 2024-25 のプレイオフのデータを取得
playoff_2024_25 = pl.from_pandas(
    shotchartdetail.ShotChartDetail(
        team_id=team_id,
        player_id=player_id,
        season_type_all_star='Playoffs',
        season_nullable='2024-25',
        context_measure_simple='FGA',
    ).get_data_frames()[0]
)

regular_season_2023_24, playoff_2023_24, regular_season_2024_25, playoff_2024_25, regular_season_2025_26

おぉ、いいね、取れてる取れてる。

001_0006.png

4. 保存

ということで、ここまで取得したデータを結合して、保存しておく。

df_2023_24 = pl.concat([
    regular_season_2023_24.with_columns(pl.lit('Regular Season').alias('Season Type')),
    playoff_2023_24.with_columns(pl.lit('Playoffs').alias('Season Type'))
])

df_2024_25 = pl.concat([
    regular_season_2024_25.with_columns(pl.lit('Regular Season').alias('Season Type')),
    playoff_2024_25.with_columns(pl.lit('Playoffs').alias('Season Type'))
])

df_2025_26 = regular_season_2025_26.with_columns(pl.lit('Regular Season').alias('Season Type'))

df_2023_24.write_csv("./shotchart_2023_24.csv")
df_2024_25.write_csv("./shotchart_2024_25.csv")
df_2025_26.write_csv("./shotchart_2025_26.csv")

df_2023_24.write_parquet("./shotchart_2023_24.parquet")
df_2024_25.write_parquet("./shotchart_2024_25.parquet")
df_2025_26.write_parquet("./shotchart_2025_26.parquet")

5. おわり!

今回はここまでにします、最後までお読みいただきありがとうございました。
次回はこれらを使用して分析していきます。
Pythonがちょっとでも書けるよって方は簡単にnba_apiを用いれば、NBAのデータを取得できることがわかったんじゃないでしょうか。

もし、NBAのデータ分析や可視化に興味あるよって方、面白そうって思った方は是非、reibniz.tech@gmail.com までご連絡ください。

今回の分析含め、NBA関連のコードはgithubで公開予定です。


$^{*1}$ NBA 2K というゲームの世界で、それぞれの選手に、例えば3Pが85、ハンドリングが90、のように数値化された能力値が割り振られるらしく、あまりに Rui がミドルレンジシュートを決めることから、思わず解説が「ミドルレンジが99じゃねえか」と言っちゃったって話。

$^{*2}$ NBAで公式に3ポイント成功率が統計値として認められるのは、82試合あるレギュラーシーズンで、82本以上決めた選手に限られるため、シーズン中ではそのペース以上に、つまり、1試合で1本以上決めている選手でランキングが作成される。チームの消化した試合数以上の3ポイント成功(FG3PM)が必要とされる。そうじゃないと、1試合でてたまたま1/1で3ポイントを決めた選手がランキング1位になるって変なことになっちゃうので。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?