ryo’s blog

日々学んだことをまとめています.

nba_apiを使って1996年ドラフトNo.1プレイヤーを決めてみた

はじめに

スター選手が多いことから伝説とされる1996年ドラフトで
誰がNo.1なのかnba_apiを使って決めてみました。

方法としては、各スタッツの合計値をもとにグラフで表示し確認しています。
言語はPythonです。


制作物

github.com


まずはnba_apiを使って、stats.nba.comから情報を取得します。
サイト内にあるサンプルコードをもとに試してみます。

from nba_api.stats.endpoints import commonplayerinfo

def main():
    # データを取得
    player_info = commonplayerinfo.CommonPlayerInfo(player_id=2544)

    # DataFrameオブジェクトに変換
    pd = player_info.player_headline_stats.get_data_frame()
    print(pd)

if __name__ == '__main__':
    main()
$ python3 main.py
   PLAYER_ID   PLAYER_NAME TimeFrame   PTS  AST  REB    PIE
0       2544  LeBron James   2021-22  25.9  6.8  6.6  0.161

いい感じに選手の情報が取得できていますね。


次にこの情報を元にmatplotを使ってグラフにしてみます。

from nba_api.stats.endpoints import commonplayerinfo
import matplotlib
import matplotlib.pyplot as plt

def main():
    # データを取得
    player_info = commonplayerinfo.CommonPlayerInfo(player_id=2544)

    # DataFrameオブジェクトに変換
    pd = player_info.player_headline_stats.get_data_frame()

    # 各項目を取得
    pts   = pd['PTS'][0]
    ast   = pd['AST'][0]
    reb   = pd['REB'][0]
    name  = pd['PLAYER_NAME'][0]
    frame = pd['TimeFrame'][0]

    # matplotの設定
    left   = [1, 2, 3]
    label  = ['PTS', 'AST', 'REB']
    height = [pts, ast, reb]
    fig    = plt.figure('NBA STATS')

    plt.bar(left,height, tick_label=label, align='center')
    plt.title(name + ' (' + frame + ')')
    for x, y in zip(left, height):
        plt.text(x, y, y, ha='center', va='bottom')
    plt.show()

if __name__ == '__main__':
    main()

実行してみる。

f:id:ryo_manba:20211223124035p:plain

おおー。いい感じにグラフにできました。
さすがレブロン、36歳でこのスタッツですからね。すごすぎる。

またplayer_idを変更することで他の選手のデータも取得できます。
以下に選手の情報がまとまっているので参考にしました。
https://github.com/djblechn-su/nba-player-team-ids/blob/master/NBA_Player_IDs.csv

f:id:ryo_manba:20211223124038p:plain

ウェイドのスタッツもこんな感じで取れます。
引退してる選手に関してはキャリアスタッツが取得できるみたいですね。


そして本題の1996年のNo.1プレイヤーを決めていきます。
調べてみると ID が連番になっているみたい(なっていない選手もいるが今回は割愛)なので、ドラフト1位から順番に60位までの情報を取ってみます。

from nba_api.stats.endpoints import commonplayerinfo
import matplotlib
import matplotlib.pyplot as plt

ID_IVERSON = 947
NB_DRAFT   = 59

def get_info(id):
    player_info = commonplayerinfo.CommonPlayerInfo(player_id=id)
    return player_info.player_headline_stats.get_data_frame()

def get_players_info(start, end):
    pd = None
    for i in range(start, end):
        try:
            pd = get_info(i)
            print(pd['PLAYER_NAME'][0])
        except:
            continue

def main():
    get_players_info(ID_IVERSON, (ID_IVERSON + NB_DRAFT))

if __name__ == '__main__':
    main()
Allen Iverson
Marcus Camby
Shareef Abdur-Rahim
Stephon Marbury
Ray Allen
Antoine Walker
Lorenzen Wright
Kerry Kittles
...(下に続く)

正しくデータが取れてそうです。

あとはポイント、アシスト、リバウンドの平均値を計算してグラフにしてみます。

from nba_api.stats.endpoints import commonplayerinfo
import matplotlib
import matplotlib.pyplot as plt

class my_nba:
    ID_IVERSON = 947
    NB_DRAFT   = 59

    def __init__(self):
        self.pd      = None
        self.index   = []
        self.score   = []
        self.players = []

    def get_info(self, id):
        """
        選手情報を取得
        """
        player_info = commonplayerinfo.CommonPlayerInfo(player_id=id)
        self.pd = player_info.player_headline_stats.get_data_frame()

    def get_players_info(self, start, end):
        """
        指定された範囲の選手情報をインスタンス変数に追加していく
        """
        index = 1
        for i in range(start, end):
            try:
                self.get_info(i)
            except:
                continue
            try:
                pts   = self.pd['PTS'][0]
                ast   = self.pd['AST'][0]
                reb   = self.pd['REB'][0]
                name  = self.pd['PLAYER_NAME'][0]
            except IndexError:
                continue
            self.players.insert(0,name)
            self.index.append(index)
            index += 1
            score = (pts + ast + reb)
            self.score.insert(0,score)

    def plot_bar_graph(self, year):
        """
        横棒グラフを表示する
        """
        plt.barh(self.index, self.score, align="center")
        plt.yticks(self.index, self.players)
        plt.title(str(year) + " Draft Players Score")
        plt.show()

def main():
    print("Please wait...")
    nba = my_nba()
    nba.get_players_info(nba.ID_IVERSON, (nba.ID_IVERSON + nba.NB_DRAFT))
    nba.plot_bar_graph(1996)

if __name__ == '__main__':
    main()

実行してみる。

f:id:ryo_manba:20211223124016p:plain

できました!(見づらいのでクリックして見てみてください)

1位 Allen Iverson
2位 Kobe Bryant
3位 Stephon Marbury
という結果となりました。

文句なしで1位はアイバーソンですね!
コービーファンとしては悔しい結果となりましたが、正しく表示できたので良しとしましょう。


終わりに

各ポジションごとに得点の重み付けを変えてみるとより面白いかなと思いました。また時間があるときに試してみようと思います。
それとPythonでグラフを線描するのが初めてだったので面白かったです。

NBA大好きなので今後も気分転換に遊んでみようと思います。
それでは良いNBAライフを!

おまけ(2003年ドラフト)

開始idをいじると他の年代も表示することができます。

f:id:ryo_manba:20211223124031p:plain

未だに現役の選手に関しては昨年のスタッツになっています。
それにしてもレブロン強すぎる。。