本文目录导读:

电脑分析球员跑动热点图,本质上是一个从原始定位数据到空间密度可视化,再到战术解读的完整流程,下面从技术实现的角度,按步骤拆解。
数据来源:热点图的原料
热点图的基础是球员位置数据,主要有几种获取方式:
| 数据源 | 精度 | 采样频率 | 典型系统 |
|---|---|---|---|
| GPS背心 | 5–1m | 5–10 Hz | Catapult, STATSports |
| 光学追踪 | 5–20cm | 25 Hz | Hawk-Eye, Second Spectrum |
| 半自动越位系统 | ~10cm | 50 Hz | FIFA SAOT |
| 广播视频+AI | 1–2m | 25 fps | 计算机视觉方案 |
每条记录通常包含:球员ID、时间戳、x坐标、y坐标(部分还有速度、加速度)。
核心分析流程
数据预处理
import pandas as pd
import numpy as np
# 读取原始追踪数据
df = pd.read_csv("tracking_data.csv")
# 筛选某球员
player = df[df['player_id'] == 7].copy()
# 坐标归一化到球场标准尺寸(如105×68米)
player['x_norm'] = player['x'] / 105
player['y_norm'] = player['y'] / 68
# 去除异常点(速度突变、越界)
player = player[(player['x_norm'].between(0,1)) &
(player['y_norm'].between(0,1))]
空间密度估计——热点图的数学核心
热点图的本质是二维核密度估计,常用方法:
方法A:KDE(核密度估计)
from scipy.stats import gaussian_kde import matplotlib.pyplot as plt positions = np.vstack([player['x_norm'], player['y_norm']]) kde = gaussian_kde(positions, bw_method=0.05) # bw控制平滑度 # 生成网格 xx, yy = np.mgrid[0:1:200j, 0:1:130j] grid = np.vstack([xx.ravel(), yy.ravel()]) density = kde(grid).reshape(xx.shape) plt.imshow(density.T, origin='lower', extent=[0,1,0,1], cmap='hot')
方法B:2D直方图(更快,适合实时)
heatmap, _, _ = np.histogram2d(
player['x_norm'], player['y_norm'],
bins=[105, 68], range=[[0,1],[0,1]]
)
方法C:时间加权密度
考虑球员在某位置停留时间,而非简单帧数:
# 每个位置按停留时长加权
player['dt'] = player['timestamp'].diff().fillna(0)
heatmap, _, _ = np.histogram2d(
player['x_norm'], player['y_norm'],
bins=[105, 68], weights=player['dt']
)
可视化渲染
- 颜色映射:
hot、jet、RdYlBu_r,低密度蓝→高密度红 - 叠加底图:把球场线、禁区、中圈画在热图之上
- 透明度:
alpha=0.6~0.8让球场线可见
from mplsoccer import Pitch
pitch = Pitch(pitch_type='statsbomb', line_zorder=2)
fig, ax = pitch.draw()
pitch.kdeplot(player['x_norm']*120, player['y_norm']*80,
ax=ax, fill=True, levels=50, cmap='hot')
进阶分析维度
单纯的位置密度只是起点,专业分析会叠加更多维度:
分时段热点
- 上半场 vs 下半场
- 每15分钟一段 → 观察体能下降导致的跑动范围收缩
分状态热点
- 进攻时 vs 防守时的位置分布
- 有球 vs 无球跑动
- 高速跑(>5.5 m/s)vs 慢跑/步行
战术角色识别
# 计算球员的"活动重心"和"活动范围" centroid = player[['x_norm','y_norm']].mean() spread = player[['x_norm','y_norm']].std() # 结合区域占比判断角色 # 例:边路占比>60% + 前场占比>50% → 边锋
对比分析
- 同位置球员横向对比
- 同一球员不同比赛对比
- 与球队整体热图叠加,看是否偏离战术要求
常用工具链
| 环节 | 工具 |
|---|---|
| 数据处理 | Python (pandas, numpy), R |
| 密度计算 | scipy, sklearn.KDE, seaborn.kdeplot |
| 可视化 | mplsoccer, matplotlib, plotly |
| 商业平台 | StatsBomb IQ, Opta Vision, Wyscout, Hudl |
| 实时系统 | Kafka + Spark Streaming + Deck.gl |
分析时的注意事项
- 采样偏差:GPS在室内/拥挤区域误差大,需滤波
- 带宽选择:KDE的
bw太大→糊成一团,太小→噪点满屏,一般0.03–0.08 - 归一化方向:必须统一进攻方向(有些数据主客队方向相反)
- 时间权重:只看帧数会高估静止区域,看停留时长更合理
- 样本量:单场热图波动大,建议多场平均或按对手类型分组
一个完整的极简示例
import pandas as pd, numpy as np
from scipy.stats import gaussian_kde
import matplotlib.pyplot as plt
from mplsoccer import Pitch
df = pd.read_csv("match.csv")
p = df[df.player_id==7][['x','y']].dropna()
kde = gaussian_kde(p.T, bw_method=0.06)
xx, yy = np.mgrid[0:120:300j, 0:80:200j]
zz = kde(np.vstack([xx.ravel(), yy.ravel()])).reshape(xx.shape)
pitch = Pitch(pitch_type='statsbomb')
fig, ax = pitch.draw()
ax.contourf(xx, yy, zz, levels=30, cmap='hot', alpha=0.75)
ax.set_title("Player 7 跑动热点图")
plt.show()
总结一句话:热点图分析 = 定位数据 → 清洗归一化 → 核密度估计 → 可视化 → 叠加战术维度解读,工具只是手段,真正的价值在于把密度分布翻译成跑位习惯、战术执行度、体能分配等可 actionable 的结论。
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。