はじめに
NCAAバスケットボールのデータ分析において、アドバンスド統計は非常に重要な役割を果たします。アドバンスド統計とは、従来の基本的な統計データを組み合わせて算出される高度な指標のことです。これらの指標は、チームやプレイヤーのパフォーマンスをより深く理解するために使用されます。
本記事では、Pythonを用いてNCAAバスケットボールのアドバンスド統計を算出する方法について解説します。コードの各部分に詳細な説明を加えているので、プログラミングに慣れていない方でも理解しやすい内容となっています。
必要なライブラリのインポート
まず、必要なPythonライブラリをインポートします。本記事では、以下のライブラリを使用します。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from math import pi
import os
- NumPy: 数値計算を効率的に行うためのライブラリ
- Pandas: データ操作と分析を行うためのライブラリ
- Matplotlib: グラフの作成と可視化を行うためのライブラリ
- Math: 数学関数を提供するPythonの標準ライブラリ
- OS: ファイルやディレクトリ操作を行うためのPythonの標準ライブラリ
データの読み込みと前処理
次に、CSVファイルからデータを読み込み、前処理を行います。
def create_advanced_stats():
# CSVファイルからデータを読み込む
df = pd.read_csv('../input/march-madness-analytics-2020/MDataFiles_Stage2/MRegularSeasonDetailedResults.csv')
# 勝利チームと敗北チームの得点を計算
df['WPts'] = df.WScore
df['LPts'] = df.LScore
pd.read_csv()
関数を使って、CSVファイルからデータをDataFrameとして読み込みます。- 勝利チーム(W)と敗北チーム(L)の得点を、新しい列
WPts
とLPts
に格納します。
ポゼッション数の計算
ポゼッション数は、チームがボールを保持している回数を表す指標です。ここでは、以下の式を用いてポゼッション数を計算します。
# 勝利チームと敗北チームのポゼッション数を計算
# ポゼッション数 = 0.96 * (フィールドゴール試投数 + ターンオーバー数 + 0.44 * フリースロー試投数 - オフェンシブリバウンド数)
wPos = df.apply(lambda row: 0.96*(row.WFGA + row.WTO + 0.44*row.WFTA - row.WOR), axis=1)
lPos = df.apply(lambda row: 0.96*(row.LFGA + row.LTO + 0.44*row.LFTA - row.LOR), axis=1)
# 両チームのポゼッション数はほぼ同じなので、平均値を使用
df['Pos'] = (wPos+lPos)/2
df['WPos'] = wPos
df['LPos'] = lPos
apply()
関数を使って、各行に対してポゼッション数の計算式を適用します。- 勝利チームと敗北チームのポゼッション数を別々に計算し、それぞれ
wPos
とlPos
に格納します。 - 両チームのポゼッション数はほぼ同じなので、平均値を
Pos
列に格納します。 - 勝利チームと敗北チームのポゼッション数を、
WPos
とLPos
列に格納します。
アドバンスドメトリクスの計算
次に、各種アドバンスドメトリクスを計算します。以下のメトリクスを算出します。
- オフェンシブ効率 (OffRtg)
- ディフェンシブ効率 (DefRtg)
- ネットレーティング (NetRtg)
- アシスト比 (AstR)
- ターンオーバー比 (TOR)
- シューティング効率 (TSP)
- 実効フィールドゴール% (eFG%)
- フリースロー試投率 (FTA Rate)
- オフェンシブリバウンド% (OREB%)
- ディフェンシブリバウンド% (DREB%)
- リバウンド% (REB%)
- PIE (Player Impact Estimate)
各メトリクスの計算式は、コード内のコメントに記載されています。
# アドバンスドメトリクスの計算
# オフェンシブ効率 (OffRtg) = 100 * (得点 / ポゼッション数)
df['WOffRtg'] = df.apply(lambda row: 100 * (row.WPts / row.WPos), axis=1)
df['LOffRtg'] = df.apply(lambda row: 100 * (row.LPts / row.LPos), axis=1)
# ディフェンシブ効率 (DefRtg) = 100 * (相手チームの得点 / 相手チームのポゼッション数)
df['WDefRtg'] = df.LOffRtg
df['LDefRtg'] = df.WOffRtg
# ネットレーティング = オフェンシブ効率 - ディフェンシブ効率
df['WNetRtg'] = df.apply(lambda row:(row.WOffRtg - row.WDefRtg), axis=1)
df['LNetRtg'] = df.apply(lambda row:(row.LOffRtg - row.LDefRtg), axis=1)
# アシスト比 : アシストでポゼッションが終了した割合
df['WAstR'] = df.apply(lambda row: 100 * row.WAst / (row.WFGA + 0.44*row.WFTA + row.WAst + row.WTO), axis=1)
df['LAstR'] = df.apply(lambda row: 100 * row.LAst / (row.LFGA + 0.44*row.LFTA + row.LAst + row.LTO), axis=1)
# ターンオーバー比 : 100ポゼッションあたりのチームのターンオーバー数
# (TO * 100) / (FGA + (FTA * 0.44) + AST + TO)
df['WTOR'] = df.apply(lambda row: 100 * row.WTO / (row.WFGA + 0.44*row.WFTA + row.WAst + row.WTO), axis=1)
df['LTOR'] = df.apply(lambda row: 100 * row.LTO / (row.LFGA + 0.44*row.LFTA + row.LAst + row.LTO), axis=1)
# シューティング効率 : シューティングの効率性を測定 (FGA/FGA3, FTA)
df['WTSP'] = df.apply(lambda row: 100 * row.WPts / (2 * (row.WFGA + 0.44 * row.WFTA)), axis=1)
df['LTSP'] = df.apply(lambda row: 100 * row.LPts / (2 * (row.LFGA + 0.44 * row.LFTA)), axis=1)
# 実効フィールドゴール% (eFG%) : 3ポイントショットの価値を考慮したフィールドゴール成功率
df['WeFGP'] = df.apply(lambda row:(row.WFGM + 0.5 * row.WFGM3) / row.WFGA, axis=1)
df['LeFGP'] = df.apply(lambda row:(row.LFGM + 0.5 * row.LFGM3) / row.LFGA, axis=1)
# フリースロー試投率 (FTA Rate) : ファウルを引き出す能力
df['WFTAR'] = df.apply(lambda row: row.WFTA / row.WFGA, axis=1)
df['LFTAR'] = df.apply(lambda row: row.LFTA / row.LFGA, axis=1)
# オフェンシブリバウンド% (OREB%) : チームのオフェンシブリバウンドの割合
df['WORP'] = df.apply(lambda row: row.WOR / (row.WOR + row.LDR), axis=1)
df['LORP'] = df.apply(lambda row: row.LOR / (row.LOR + row.WDR), axis=1)
# ディフェンシブリバウンド% (DREB%) : チームのディフェンシブリバウンドの割合
df['WDRP'] = df.apply(lambda row: row.WDR / (row.WDR + row.LOR), axis=1)
df['LDRP'] = df.apply(lambda row: row.LDR / (row.LDR + row.WOR), axis=1)
# リバウンド% (REB%) : チームの総リバウンドの割合
df['WRP'] = df.apply(lambda row: (row.WDR + row.WOR) / (row.WDR + row.WOR + row.LDR + row.LOR), axis=1)
df['LRP'] = df.apply(lambda row: (row.LDR + row.LOR) / (row.WDR + row.WOR + row.LDR + row.LOR), axis=1)
# PIE (Player Impact Estimate) : チームのパフォーマンスを測定
# 高いPIE%は勝利と強い相関がある
wtmp = df.apply(lambda row: row.WPts + row.WFGM + row.WFTM - row.WFGA - row.WFTA + row.WDR + 0.5*row.WOR + row.WAst +row.WStl + 0.5*row.WBlk - row.WPF - row.WTO, axis=1)
ltmp = df.apply(lambda row: row.LPts + row.LFGM + row.LFTM - row.LFGA - row.LFTA + row.LDR + 0.5*row.LOR + row.LAst +row.LStl + 0.5*row.LBlk - row.LPF - row.LTO, axis=1)
df['WPIE'] = wtmp/(wtmp + ltmp)
df['LPIE'] = ltmp/(wtmp + ltmp)
結果の保存
最後に、計算結果をCSVファイルに保存します。
# 結果をCSVファイルに保存
df.to_csv('NCAASeasonDetailedResultsEnriched.csv', index=False)
return df
create_advanced_stats()
to_csv()
関数を使って、DataFrameをCSVファイルに保存します。index=False
を指定することで、行インデックスを保存しないようにします。create_advanced_stats()
関数を呼び出して、アドバンスド統計の計算を実行します。
まとめ
本記事では、Pythonを用いてNCAAバスケットボールのアドバンスド統計を算出する方法について解説しました。アドバンスド統計を理解し、適切に使用することで、チームやプレイヤーのパフォーマンスをより深く分析することができます。
プログラミングに慣れていない方でも、コードの各部分に詳細な説明を加えているので、理解しやすい内容となっています。ぜひ、本記事を参考にして、NCAAバスケットボールのデータ分析に挑戦してみてください。
Kaggle ノートブック
NCAA大学バスケットボールの試合データ分析(advanced_stats)
Explore and run machine learning code with Kaggle Notebooks | Using data from Google Cloud & NCAA® March Madness Analytics
コメント