实用脚本如何分析定位球战术的多样性
分析定位球战术多样性,核心是把"定位球"拆解成可量化的维度,再用脚本做统计、聚类和可视化,下面给出一套可落地的思路和脚本框架(Python + 常见足球数据格式)。

先定义"多样性"的量化维度
定位球战术多样性可以从以下维度衡量:
| 维度 | 指标示例 |
|---|---|
| 类型多样性 | 角球/任意球/界外球/点球的比例分布、香农熵 |
| 区域多样性 | 开球落点热区、传球起点-终点分布 |
| 战术模式 | 短传/长传、前点/后点、战术配合次数 |
| 人员参与 | 参与人数、跑位路线数量 |
| 时间节奏 | 从鸣哨到开球的秒数分布 |
| 结果多样性 | 射门/进球/二次进攻比例 |
香农熵是衡量多样性的好工具:分布越均匀,熵越高,战术越"多样"。
数据准备
假设你有一份事件数据(Opta/StatsBomb/Wyscout 风格),字段大致为:
# set_pieces.csv 示例字段
# match_id, team, type(角球/任意球/界外球), minute,
# start_x, start_y, end_x, end_y, n_passes, outcome(shot/goal/clear)
import pandas as pd
df = pd.read_csv("set_pieces.csv")
核心分析脚本
类型分布与香农熵
import numpy as np
from collections import Counter
def shannon_entropy(series):
counts = Counter(series)
total = sum(counts.values())
probs = np.array([c/total for c in counts.values()])
return -np.sum(probs * np.log2(probs))
for team, g in df.groupby("team"):
ent = shannon_entropy(g["type"])
print(f"{team}: 类型熵={ent:.2f}, 样本={len(g)}")
落点区域多样性(网格化 + 熵)
def zone(x, y, nx=6, ny=3): # 把场地切成 6x3 网格
return (int(x // (100/nx)), int(y // (100/ny)))
df["zone"] = df.apply(lambda r: zone(r["end_x"], r["end_y"]), axis=1)
for team, g in df.groupby("team"):
print(team, "落点熵:", shannon_entropy(g["zone"]))
战术模式聚类(KMeans)
把每次定位球的"传球序列特征"作为向量:传球次数、平均传球长度、横向/纵向位移、参与人数等,聚类后看每队使用的模式数量和各模式占比。
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
feat = df[["n_passes", "start_x", "end_x", "end_y"]].fillna(0)
X = StandardScaler().fit_transform(feat)
km = KMeans(n_clusters=5, random_state=0).fit(X)
df["cluster"] = km.labels_
# 每队使用的战术簇数量 & 分布熵
for team, g in df.groupby("team"):
print(team, "使用簇:", g["cluster"].nunique(),
"簇分布熵:", shannon_entropy(g["cluster"]))
时间节奏多样性
# 假设有 whistle_time 和 delivery_time 字段
df["delay"] = df["delivery_time"] - df["whistle_time"]
for team, g in df.groupby("team"):
print(team, "平均开球延迟:", g["delay"].mean(),
"标准差:", g["delay"].std()) # 标准差大=节奏更多变
结果多样性
for team, g in df.groupby("team"):
dist = g["outcome"].value_counts(normalize=True)
print(team, "结果熵:", shannon_entropy(g["outcome"]), "\n", dist)
综合"多样性评分"
把各维度熵归一化后加权求和,得到一个 0–1 的多样性指数:
def diversity_score(g):
dims = {
"type": shannon_entropy(g["type"]),
"zone": shannon_entropy(g["zone"]),
"cluster":shannon_entropy(g["cluster"]),
"outcome":shannon_entropy(g["outcome"]),
}
# 归一化到 [0,1]:除以理论最大熵 log2(类别数)
max_ent = {"type": np.log2(g["type"].nunique()),
"zone": np.log2(g["zone"].nunique()),
"cluster": np.log2(g["cluster"].nunique()),
"outcome": np.log2(g["outcome"].nunique())}
norm = {k: v/max_ent[k] if max_ent[k] > 0 else 0 for k, v in dims.items()}
weights = {"type":0.2, "zone":0.3, "cluster":0.3, "outcome":0.2}
return sum(norm[k]*weights[k] for k in dims), norm
for team, g in df.groupby("team"):
score, detail = diversity_score(g)
print(f"{team}: 综合多样性={score:.2f}", detail)
可视化(可选)
- 落点热力图:
matplotlib/mplsoccer画 pitch + hexbin - 战术簇雷达图:每队各簇占比画雷达图,一眼看出模式偏向
- 熵的条形图:对比各队各维度熵
import mplsoccer pitch = mplsoccer.Pitch() fig, ax = pitch.draw() pitch.scatter(df.end_x, df.end_y, ax=ax, alpha=0.3)
关键注意事项
- 样本量:定位球单场很少,建议按赛季或多场累计,否则熵不稳定。
- 对手调整:可拆"对阵强队/弱队"分别算,看战术是否因对手而变。
- 坐标统一:不同数据源坐标系不同,先归一化到 0–100。
- 区分定位球子类:角球与任意球战术逻辑差别大,最好分类别算多样性再汇总。
- 熵的陷阱:熵高不等于"好",只代表"不重复";要结合结果效率(如每类战术的进球率)一起解读。
最小可用流程总结
读数据 → 分类别清洗 → 定义特征向量
→ 各维度算熵 → 聚类看模式 → 加权综合分 → 可视化对比
如果需要,我可以针对你手上的具体数据字段(StatsBomb JSON / Wyscout / 自采表)写出可直接跑的清洗+分析脚本,告诉我是哪种格式即可。