两队边路突破能力对比(Python案例)
下面用 StatsBomb 开放数据 + mplsoccer 做一个完整的边路突破能力对比案例,涵盖数据获取、指标构建、可视化。

核心思路
"边路突破能力"不是一个官方统计项,需要自己构造指标,常用组合:
| 指标 | 含义 |
|---|---|
| 边路区域触球/推进次数 | 活动量 |
| 边路 1v1 过人(dribble)成功次数 | 突破成功率 |
| 边路带球推进距离(carry progress) | 推进威胁 |
| 边路传中/倒三角传球 | 突破后的产出 |
| 边路进入进攻三区次数 | 最终威胁区域 |
关键在于:先按 x 坐标把球场切成左/中/右三块,再统计边路区域的事件。
数据准备
pip install statsbombpy mplsoccer pandas numpy matplotlib
from statsbombpy import sb import pandas as pd # 以曼城 vs 皇马(2022欧冠)为例 matches = sb.matches(competition_id=16, season_id=44) # 欧冠2021/22 match_id = matches.iloc[0]['match_id'] events = sb.events(match_id=match_id)
事件表关键字段:type、location、player、team、under_pressure、pass_end_location、carry_end_location 等。
构造边路突破指标
import numpy as np
def side_zone(x):
"""按 x 坐标划分左右边路(StatsBomb 球场 120x80,x 为纵向)"""
if x < 20 or x > 100: # 两端禁区前后区域
return 'central'
if x < 40 or x > 80:
return 'wide'
return 'central'
# 提取坐标
def get_xy(loc):
if isinstance(loc, list) and len(loc) == 2:
return loc[0], loc[1]
return np.nan, np.nan
events[['x', 'y']] = events['location'].apply(
lambda l: pd.Series(get_xy(l))
)
# 只看边路(y 靠近边线:y<18 或 y>62 视为边路通道)
def is_wing(y):
return (y < 18) or (y > 62)
events['on_wing'] = events['y'].apply(lambda v: is_wing(v) if pd.notna(v) else False)
# 1) 边路带球(carry)
carries = events[(events['type'] == 'Carry') & events['on_wing']].copy()
carries['carry_dist'] = carries.apply(
lambda r: np.hypot(
r['carry_end_location'][0] - r['x'],
r['carry_end_location'][1] - r['y']
) if isinstance(r['carry_end_location'], list) else 0, axis=1
)
# 2) 边路过人(dribble)
dribbles = events[(events['type'] == 'Dribble') & events['on_wing']].copy()
dribbles['success'] = dribbles['dribble_outcome'] == 'Complete'
# 3) 边路传中(cross,进入禁区)
crosses = events[(events['type'] == 'Pass') & events['on_wing']].copy()
def is_cross(r):
if not isinstance(r['pass_end_location'], list): return False
ex, ey = r['pass_end_location']
return ex > 102 and 18 < ey < 62
crosses['is_cross'] = crosses.apply(is_cross, axis=1)
汇总对比表:
summary = pd.DataFrame({
'边路带球次数': carries.groupby('team').size(),
'边路带球总距离': carries.groupby('team')['carry_dist'].sum().round(0),
'边路过人尝试': dribbles.groupby('team').size(),
'边路过人成功': dribbles[dribbles['success']].groupby('team').size(),
'边路传中': crosses[crosses['is_cross']].groupby('team').size(),
}).fillna(0)
summary['过人成功率%'] = (summary['边路过人成功'] / summary['边路过人尝试'] * 100).round(1)
print(summary.T)
输出大致形如:
team A队 B队
边路带球次数 58 41
边路带球总距离 620 430
边路过人成功 12 6
过人成功率% 52.2 33.3
边路传中 9 4
可视化对比
1)雷达图(多指标综合对比)
import matplotlib.pyplot as plt
from math import pi
metrics = ['边路带球次数', '边路带球总距离', '边路过人成功', '边路传中']
teams = summary.index.tolist()
# 归一化到 0-1
norm = summary[metrics] / summary[metrics].max()
angles = [n / len(metrics) * 2 * pi for n in range(len(metrics))]
angles += angles[:1]
fig, ax = plt.subplots(figsize=(6, 6), subplot_kw=dict(polar=True))
for team in teams:
vals = norm.loc[team].tolist()
vals += vals[:1]
ax.plot(angles, vals, label=team)
ax.fill(angles, vals, alpha=0.15)
ax.set_xticks(angles[:-1])
ax.set_xticklabels(metrics)
ax.legend(loc='upper right', bbox_to_anchor=(1.3, 1.1))'两队边路突破能力雷达对比')
plt.show()
2)边路活动热力图(mplsoccer)
from mplsoccer import Pitch
import matplotlib.pyplot as plt
pitch = Pitch(pitch_type='statsbomb', line_zorder=2)
fig, axes = pitch.draw(nrows=1, ncols=2, figsize=(14, 6))
for ax, team in zip(axes, teams):
team_carries = carries[carries['team'] == team]
bin_stat = pitch.bin_statistic(
team_carries['x'], team_carries['y'],
statistic='count', bins=(12, 8)
)
pitch.heatmap(bin_stat, ax=ax, cmap='Reds')
ax.set_title(f'{team} 边路带球分布')
plt.show()
3)边路推进折线(按15分钟区间)
events['minute_bin'] = (events['minute'] // 15) * 15
wing_carry_by_time = (
carries.assign(bin=(carries['minute'] // 15) * 15)
.groupby(['bin', 'team']).size().unstack(fill_value=0)
)
wing_carry_by_time.plot(kind='bar', figsize=(10, 5))
plt.xlabel('比赛分钟(每15分钟)')
plt.ylabel('边路带球次数')'边路突破活跃度的时段分布')
plt.legend(title='球队')
plt.show()
进阶建议(真实分析场景)
- 区分左右路:
y<18算右路(StatsBomb y 从下到上),y>62算左路,可以拆成"左路突破 vs 右路突破"两栏对比。 - 考虑对手强度:同一球队打强队/弱队边路数据差异大,需样本累积(多场比赛合并)。
- 用 xT / VAEP 量化威胁:单纯计数会高估"原地无效带球",可引入 xT(expected threat) 或 VAEP 框架,把每次边路推进算成实际创造价值。
- 压迫下突破:加上
under_pressure == True过滤,得到"高压下边路突破",这更能反映真实突破能力。 - 球员级下钻:用
player字段 groupby,找出各队边路突破核心球员。
小结
| 步骤 | 关键代码 | 目的 |
|---|---|---|
| 1 | events['type']=='Carry' + y 坐标过滤 |
锁定边路事件 |
| 2 | 计算 carry 距离 / 过人成功率 | 构造突破指标 |
| 3 | groupby('team') 汇总 |
两队横向对比 |
| 4 | 雷达图 + 热力图 + 时序图 | 多维可视化 |
| 5 | 加入 xT / 压迫条件 | 提升分析质量 |
这个模板可以直接套用到任意 StatsBomb 比赛或你的自采数据(只需字段对齐:type、location、team、minute),如果你有具体球队/联赛数据,我可以帮你把代码改成对应格式。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播