足球定位球战术多样性分析系统 - Python案例
下面通过一个完整的Python案例,演示如何用数据分析方法量化定位球战术的多样性。

问题定义
目标:分析一支球队(或联赛)在定位球(角球、任意球、点球)中的战术多样性,回答:
- 战术类型是否丰富?
- 是否过度依赖某一种套路?
- 不同比赛/时段的战术变化趋势?
多样性维度:
- 战术类型(短传、长传、战术配合、直接射门…)
- 落点区域(前点、后点、中路、禁区外)
- 参与人数
- 传球次数
- 时间分布
数据准备(模拟数据)
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from collections import Counter
import math
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
np.random.seed(42)
# 模拟:某队一个赛季的定位球记录
n = 200
set_pieces = pd.DataFrame({
'match_id': np.random.randint(1, 31, n),
'minute': np.random.randint(1, 95, n),
'type': np.random.choice(['角球', '任意球', '点球'], n, p=[0.5, 0.45, 0.05]),
# 战术类型
'tactic': np.random.choice(
['短传配合', '长传冲吊', '战术跑位', '直接射门', '二次进攻'],
n, p=[0.2, 0.35, 0.2, 0.15, 0.1]
),
# 落点区域
'zone': np.random.choice(['前点', '后点', '中路', '禁区外'], n,
p=[0.3, 0.25, 0.3, 0.15]),
# 参与球员数
'players_involved': np.random.randint(1, 8, n),
# 传球次数
'passes': np.random.randint(0, 6, n),
# 结果
'outcome': np.random.choice(['进球', '射门', '被解围', '失误'],
n, p=[0.08, 0.22, 0.55, 0.15])
})
print(set_pieces.head())
print(f"\n总记录数: {len(set_pieces)}")
多样性量化指标
1 香农熵(Shannon Entropy)
熵越高,战术分布越均匀,多样性越强。
def shannon_entropy(series):
"""计算香农熵(归一化到0-1)"""
counts = series.value_counts(normalize=True)
entropy = -sum(p * math.log2(p) for p in counts if p > 0)
max_entropy = math.log2(len(counts)) if len(counts) > 1 else 1
return entropy / max_entropy if max_entropy > 0 else 0
# 各维度多样性
dims = ['tactic', 'zone', 'outcome']
print("=== 各维度香农熵(0-1,越高越多样)===")
for d in dims:
print(f"{d:10s}: {shannon_entropy(set_pieces[d]):.3f}")
2 辛普森多样性指数(Simpson Index)
def simpson_index(series):
"""1 - Σp²,越接近1越多样"""
p = series.value_counts(normalize=True)
return 1 - (p ** 2).sum()
print("\n=== 辛普森多样性指数 ===")
for d in dims:
print(f"{d:10s}: {simpson_index(set_pieces[d]):.3f}")
3 组合多样性(战术×落点)
# 组合战术:tactic + zone 视为一个"复合战术"
set_pieces['combo'] = set_pieces['tactic'] + ' @ ' + set_pieces['zone']
print(f"复合战术种类数: {set_pieces['combo'].nunique()}")
print(f"复合战术熵值: {shannon_entropy(set_pieces['combo']):.3f}")
# 各类型定位球的复合多样性
print("\n=== 分类型定位球的复合多样性 ===")
for t in set_pieces['type'].unique():
sub = set_pieces[set_pieces['type'] == t]
print(f"{t}: 种类={sub['combo'].nunique()}, 熵={shannon_entropy(sub['combo']):.3f}, 样本={len(sub)}")
可视化分析
1 战术分布
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
for ax, col in zip(axes, ['tactic', 'zone', 'outcome']):
counts = set_pieces[col].value_counts()
ax.barh(counts.index, counts.values, color=sns.color_palette("Set2"))
ax.set_title(f'{col} 分布 (熵={shannon_entropy(set_pieces[col]):.2f})')
ax.set_xlabel('次数')
plt.tight_layout()
plt.show()
2 不同定位球类型下的战术热力图
pivot = pd.crosstab(set_pieces['type'], set_pieces['tactic'], normalize='index')
plt.figure(figsize=(10, 4))
sns.heatmap(pivot, annot=True, fmt='.2f', cmap='YlGnBu')'不同定位球类型下的战术占比')
plt.ylabel('定位球类型')
plt.xlabel('战术类型')
plt.tight_layout()
plt.show()
3 多样性随时间变化(滚动窗口)
set_pieces_sorted = set_pieces.sort_values('match_id')
# 按比赛计算战术熵
match_entropy = set_pieces_sorted.groupby('match_id')['tactic'].apply(shannon_entropy)
plt.figure(figsize=(12, 5))
plt.plot(match_entropy.index, match_entropy.values, marker='o', label='每场战术熵')
plt.axhline(match_entropy.mean(), color='r', linestyle='--',
label=f'赛季均值={match_entropy.mean():.2f}')
plt.xlabel('比赛编号')
plt.ylabel('战术多样性(归一化熵)')'定位球战术多样性随赛季变化')
plt.legend()
plt.grid(alpha=0.3)
plt.show()
# 5场滚动平均
plt.figure(figsize=(12, 5))
plt.plot(match_entropy.rolling(5, min_periods=1).mean().values,
color='green', linewidth=2)'战术多样性(5场滚动平均)')
plt.xlabel('比赛编号')
plt.ylabel('熵')
plt.grid(alpha=0.3)
plt.show()
深入分析
1 战术集中度分析(是否过度依赖某套路)
# HHI(赫芬达尔指数):越大越集中
def hhi(series):
p = series.value_counts(normalize=True)
return (p ** 2).sum()
print("=== 战术集中度 HHI(越低越分散)===")
for d in ['tactic', 'zone', 'combo']:
print(f"{d:8s}: {hhi(set_pieces[d]):.3f}, 最高占比={set_pieces[d].value_counts(normalize=True).max():.2%}")
2 战术效率对比(哪套战术最有效?)
# 定义成功率
set_pieces['success'] = set_pieces['outcome'].isin(['进球', '射门'])
efficiency = set_pieces.groupby('tactic').agg(
使用次数=('tactic', 'size'),
成功率=('success', 'mean'),
平均参与人数=('players_involved', 'mean'),
平均传球=('passes', 'mean')
).round(2).sort_values('成功率', ascending=False)
print("\n=== 各战术效率 ===")
print(efficiency)
3 输出策略建议
# 找出"低使用率+高效率"的战术 → 潜力战术
low_use = efficiency['使用次数'] < efficiency['使用次数'].median()
high_eff = efficiency['成功率'] > efficiency['成功率'].median()
print("\n【潜力战术】(使用少但成功率高):")
print(efficiency[low_use & high_eff])
print("\n【需优化战术】(使用多但成功率低):")
print(efficiency[~low_use & ~high_eff])
分析结论示例
| 指标 | 数值 | 解读 |
|---|---|---|
| 战术熵 | 72 | 战术分布较丰富 |
| 落点熵 | 65 | 落点变化中等 |
| 复合熵 | 88 | 组合套路多样 |
| HHI(tactic) | 28 | 无明显垄断 |
| 最高占比战术 | 长传冲吊 35% | 略微偏重 |
- 该队定位球基础战术种类丰富,但长传冲吊占比过高(35%),存在可预测性。
- 短传配合成功率高但使用率仅20%,属"潜力战术",建议增加。
- 落点集中在前点+中路(60%),后点利用不足。
- 赛季中段多样性下降,可能是对手针对性防守导致。
扩展方向
- 使用真实数据:StatsBomb、Opta、Wyscout API
- 加入对手因素:防守方阵型 → 多因素方差分析
- 空间分析:用
mplsoccer绘制传球起终点热图 - 机器学习:用聚类(KMeans)自动识别"战术模式"
- 时序模型:LSTM预测下场比赛可能采用的战术
# 示例:KMeans自动聚类战术模式
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
features = pd.get_dummies(set_pieces[['tactic', 'zone']], drop_first=False)
X = StandardScaler().fit_transform(features)
set_pieces['cluster'] = KMeans(n_clusters=4, random_state=0, n_init=10).fit_predict(X)
print(set_pieces.groupby('cluster')[['tactic', 'zone']].agg(lambda x: x.mode()[0]))
核心思想:把"战术多样性"这个抽象概念,转化为熵、辛普森指数、HHI、组合种类数等可量化指标,再通过分组、时序、聚类等方法进行对比,最终输出可执行的战术建议。