用Python分析两队中场控制力对比
中场控制力是足球分析的核心指标之一,下面我给出一个完整的分析框架和可运行的案例代码。

中场控制力的量化指标
| 维度 | 具体指标 |
|---|---|
| 控球 | 控球率、传球次数、传球成功率、向前传球比例 |
| 推进 | progressive passes(渐进传球)、带球推进距离 |
| 压迫 | 抢断、拦截、反抢成功次数(PPDA) |
| 区域 | 中场三区触球次数、中场赢得球权次数 |
| 对抗 | 中场区域地面对抗成功率 |
完整案例代码
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
# 中文显示设置
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# ============ 1. 构造示例数据(实际可替换为StatsBomb/FBref/足球数据API)============
data = {
'指标': ['控球率(%)', '传球次数', '传球成功率(%)', '向前传球占比(%)',
'中场三区触球', '抢断', '拦截', '中场夺回球权', '地面对抗成功率(%)'],
'球队A(曼城)': [65, 720, 91, 38, 285, 12, 9, 24, 58],
'球队B(利物浦)': [35, 410, 84, 45, 210, 18, 14, 31, 62],
}
df = pd.DataFrame(data).set_index('指标')
# ============ 2. 归一化处理(不同量纲指标对比)============
def normalize(series):
return (series - series.min()) / (series.max() - series.min() + 1e-9)
df_norm = df.apply(normalize, axis=1)
# ============ 3. 雷达图对比 ============
labels = df_norm.index.tolist()
angles = np.linspace(0, 2 * np.pi, len(labels), endpoint=False).tolist()
angles += angles[:1]
fig, ax = plt.subplots(figsize=(9, 9), subplot_kw=dict(polar=True))
for team, color in zip(df_norm.columns, ['#1f77b4', '#d62728']):
values = df_norm[team].tolist()
values += values[:1]
ax.plot(angles, values, 'o-', linewidth=2, label=team, color=color)
ax.fill(angles, values, alpha=0.2, color=color)
ax.set_xticks(angles[:-1])
ax.set_xticklabels(labels, fontsize=11)
ax.set_title('中场控制力对比雷达图', fontsize=15, pad=20)
ax.legend(loc='upper right', bbox_to_anchor=(1.2, 1.1))
plt.tight_layout()
plt.savefig('midfield_radar.png', dpi=150)
plt.show()
# ============ 4. 中场控制力综合评分 ============
# 权重(可根据战术偏好调整)
weights = {
'控球率(%)': 0.15, '传球次数': 0.10, '传球成功率(%)': 0.15,
'向前传球占比(%)': 0.15, '中场三区触球': 0.15,
'抢断': 0.05, '拦截': 0.05, '中场夺回球权': 0.10,
'地面对抗成功率(%)': 0.10,
}
score = {}
for team in df.columns:
score[team] = sum(df_norm.loc[idx, team] * w for idx, w in weights.items())
print("=" * 40)
print("中场控制力综合评分(0-1):")
for team, s in score.items():
print(f" {team}: {s:.3f}")
print("=" * 40)
# ============ 5. 差异柱状图 ============
diff = df['球队A(曼城)'] - df['球队B(利物浦)']
fig, ax = plt.subplots(figsize=(10, 5))
colors = ['green' if x > 0 else 'red' for x in diff]
ax.barh(diff.index, diff.values, color=colors, alpha=0.7)
ax.axvline(0, color='black', linewidth=0.8)
ax.set_xlabel('差值(球队A - 球队B)')
ax.set_title('两队中场指标差异对比')
plt.tight_layout()
plt.savefig('midfield_diff.png', dpi=150)
plt.show()
如何解读结果
示例输出结论(基于上述模拟数据):
- 曼城(A队):控球率、传球量、传球成功率、中场触球显著占优 → 控制型中场,通过传控压制对手
- 利物浦(B队):向前传球占比、抢断、拦截、中场夺回球权更高 → 压迫反击型中场,通过高位逼抢夺回球权后快速推进
综合评分通常显示:曼城控球维度占优,但中场"夺回球权"维度利物浦更强,说明两队中场风格不同而非谁绝对更"强"。
真实数据获取渠道
# 方案1:FBref(免费) # pip install soccerdata import soccerdata as sd fbref = sd.FBref(leagues="ENG-Premier League", seasons="2023-2024") team_stats = fbref.read_team_season_stats(stat_type="possession") # 方案2:StatsBomb开源数据(事件级数据,可算PPDA) # https://github.com/statsbomb/open-data # 方案3:Understat(xG相关) # pip install understatapi
进阶建议
- PPDA(防守压迫强度):用StatsBomb事件数据计算,
对手传球次数 / 己方防守动作次数,值越低压迫越强 - 中场区域热图:用
mplsoccer绘制中场三区触球热力图,直观对比活动范围 - 时间切片分析:分上下半场/15分钟段看中场控制力变化,识别体能拐点
- 对手强度校正:用同联赛平均值做标准化,避免对手强弱带来的偏差
需要我针对某个具体数据源(如StatsBomb事件数据)写一份可落地的完整分析脚本吗?