スポーツデータ分析では、数値を集計するだけでは十分ではありません。
選手の走行距離、パス数、シュート数、時間帯ごとの変化などをグラフとして可視化することで、表だけでは見つけにくい傾向を理解しやすくなります。
本記事では、Python、pandas、Matplotlibを利用して、スポーツデータを基本的なグラフへ変換する方法を紹介します。
なぜデータ可視化が重要なのか
例えば、次のようなデータがあるとします。
Player A: 10.2 km
Player B: 11.5 km
Player C: 9.8 km
Player D: 12.1 km
数値を見るだけでも比較できますが、選手数が20人、50人と増えていくと判断が難しくなります。
グラフにすると、
- 最大値
- 最小値
- 外れ値
- 時間変化
- 選手間の違い
などを直感的に確認できます。
必要なライブラリを準備する
今回は以下のライブラリを利用します。
pip install pandas matplotlib
Pythonコードでは次のように読み込みます。
import pandas as pd
import matplotlib.pyplot as plt
サンプルデータを読み込む
例えば、以下のCSVファイルを用意します。
player,minutes,distance,passes,shots
Player A,90,10.2,54,3
Player B,90,11.5,67,1
Player C,75,9.8,42,4
Player D,90,12.1,71,2
Player E,60,7.4,38,2
pandasで読み込みます。
df = pd.read_csv("player_stats.csv")
print(df.head())
まずはデータ構造を確認します。
print(df.info())
可視化を行う前に、欠損値やデータ型に問題がないか確認することが重要です。
棒グラフで選手を比較する
最も基本的なのが棒グラフです。
例えば走行距離を比較します。
plt.bar(
df["player"],
df["distance"]
)
plt.xlabel("Player")
plt.ylabel("Distance (km)")
plt.title("Distance by Player")
plt.show()
棒グラフは、
- 選手ごとの比較
- チームごとの比較
- 試合ごとの比較
などに向いています。
ただしカテゴリ数が多すぎる場合は読みにくくなるため、上位10件だけ表示するなどの工夫も必要です。
並び替えると比較しやすい
グラフを作る前にデータを並び替えると、より読みやすくなります。
sorted_df = df.sort_values(
"distance",
ascending=False
)
plt.bar(
sorted_df["player"],
sorted_df["distance"]
)
plt.show()
順位が重要なデータでは、並び替えを行うだけでも視認性が大きく向上します。
折れ線グラフで時間変化を見る
スポーツでは時間による変化も重要です。
例えば15分ごとのチーム走行距離が以下だったとします。
time_data = pd.DataFrame({
"minute": [15, 30, 45, 60, 75, 90],
"distance": [12.5, 13.1, 12.8, 11.9, 11.2, 10.6]
})
折れ線グラフにします。
plt.plot(
time_data["minute"],
time_data["distance"],
marker="o"
)
plt.xlabel("Minute")
plt.ylabel("Distance")
plt.title("Distance Over Time")
plt.show()
このような可視化を利用すると、
- 後半に運動量が減っている
- 特定時間帯で変化がある
といった傾向を把握しやすくなります。
散布図で2つの指標を比較する
2つの数値の関係を見る場合は散布図が便利です。
例えば、走行距離とパス数を比較します。
plt.scatter(
df["distance"],
df["passes"]
)
plt.xlabel("Distance")
plt.ylabel("Passes")
plt.title("Distance vs Passes")
plt.show()
散布図を見ることで、
「走行距離が多い選手ほどパス数も多いのか」
といった関係を確認できます。
ただし、グラフ上で関係が見えても、すぐに因果関係があると判断してはいけません。
相関係数も確認する
数値同士の関係を見る場合は、相関係数も参考になります。
correlation = df[
["distance", "passes", "shots"]
].corr()
print(correlation)
例えば、
distance / passes = 0.72
という結果が出たとしても、
「走行距離を増やせば必ずパス数が増える」
という意味ではありません。
データの背景や試合状況も含めて解釈する必要があります。
出場時間を考慮する
スポーツデータでは、単純な合計値だけを比較すると公平ではない場合があります。
例えば90分出場した選手と30分出場した選手を比較すると、前者の走行距離やパス数が多くなりやすいでしょう。
そこで「90分あたり」の指標を作ります。
df["passes_per_90"] = (
df["passes"] /
df["minutes"] *
90
)
シュート数も同様です。
df["shots_per_90"] = (
df["shots"] /
df["minutes"] *
90
)
これにより、出場時間が異なる選手同士でも比較しやすくなります。
複数指標を一度に表示しすぎない
可視化でよくある失敗の一つが、1つのグラフに大量の情報を詰め込むことです。
例えば、
- Distance
- Passes
- Shots
- Goals
- Tackles
- Sprint
- Possession
をすべて同じグラフにすると、何を伝えたいのか分かりにくくなります。
基本的には、
1グラフ
↓
1つの質問
と考えると整理しやすくなります。
例えば、
誰が最も長く走ったのか?
なら走行距離だけを表示します。
後半に運動量が低下しているか?
なら時間別データを表示します。
ダッシュボードを作る場合
分析対象が増えてくると、複数のグラフをまとめたダッシュボードが便利になります。
Pythonでは、
- Streamlit
- Plotly Dash
- Jupyter Notebook
などを利用できます。
例えばStreamlitなら、
import streamlit as st
st.title("Sports Data Dashboard")
st.bar_chart(
df.set_index("player")["distance"]
)
のように、比較的少ないコードで簡単な分析画面を作れます。
Webサービスでも可視化は重要
データ可視化の考え方は、スポーツ分析だけに限定されません。
Webサービスでは、
- アクセス数
- ユーザー利用時間
- デバイス比率
- ページ別閲覧数
- エラー発生率
などを可視化できます。
例えば、WINMYR のようなデジタルプラットフォームをデータ分析のケースとして考える場合、スポーツコンテンツに関する利用傾向や、モバイル・デスクトップ別のアクセス状況などをグラフ化することで、数字だけでは分かりにくい変化を把握しやすくなります。
スポーツデータでもWebサービスデータでも、
収集
↓
整理
↓
集計
↓
可視化
↓
解釈
という基本的な分析プロセスは共通しています。
可視化するときの注意点
グラフを作るときには、次のポイントも重要です。
軸の単位を書く
Distance
だけではなく、
Distance (km)
と書く方が分かりやすくなります。
データ期間を明確にする
1試合のデータなのか、1シーズンなのかで意味が大きく変わります。
サンプル数を確認する
少ないデータから一般的な結論を出さないよう注意します。
見た目より読みやすさを優先する
装飾を増やしすぎるより、データの違いが分かるシンプルなグラフの方が実用的です。
AI分析の前にも可視化する
機械学習を利用する場合でも、いきなりモデルへデータを入力するのはおすすめできません。
まず可視化することで、
- 外れ値
- データ偏り
- 欠損
- 不自然な分布
- 指標間の関係
を発見できることがあります。
基本的な流れとしては、
Data
↓
Cleaning
↓
Visualization
↓
Feature Engineering
↓
Machine Learning
という順番で進めると、データを理解したうえでモデルを構築できます。
まとめ
スポーツデータ分析では、可視化を利用することで大量の数値を理解しやすい形へ変換できます。
特に基本として覚えておきたいのは、
- 棒グラフ:カテゴリ比較
- 折れ線グラフ:時間変化
- 散布図:数値同士の関係
- 相関分析:指標間の関係確認
- Per 90:出場時間を考慮した比較
です。
高度なAIモデルを導入する前に、まずデータを整理し、グラフとして観察することが重要です。
「グラフを作ること」自体を目的にするのではなく、何を知りたいのかを決め、その質問に適した可視化方法を選択することが、実用的なデータ分析につながります。