python案例怎么看两队边路突破能力对比?

wen python案例 3

Python实战解析:如何用数据可视化对比两支球队的边路突破能力?

python案例怎么看两队边路突破能力对比?


目录导读

  1. 为什么要用Python分析边路突破?——从战术到数据
  2. 数据从哪来?常见足球数据字段与含义
  3. 核心指标拆解:不是只有“过人次数”那么简单
  4. Python实战案例:两支球队边路突破对比全流程
    • 1 数据清洗与筛选(左/右边路事件提取)
    • 2 计算核心指标(成功率、推进距离、传中威胁)
    • 3 可视化对比:雷达图 + 热区图 + 时序流
  5. 常见问题QA(问答环节)
  6. 数据告诉你的,和教练看到的一样吗?

为什么要用Python分析边路突破?——从战术到数据

现代足球早已进入“数据决策”时代,当教练说“我们要加强边路进攻”时,翻译成数据语言就是:我们需要在对手的30米区两侧创造更多有效触球、成功过人和高质量传中

光看赛后统计里的“过人次数”是远远不够的,A队左边锋10次尝试过人成功7次,B队右边锋8次尝试成功6次——单纯看成功率B队更高,但A队每次过人都发生在本方半场,对球门威胁不大,这就暴露了传统统计的局限。

Python的厉害之处在于:你可以把比赛事件流(event stream)数据导入DataFrame,通过自定义公式筛选出“发生在进攻三区、且方向朝向对方球门”的带球推进,再结合速度、方向角度、后续传中或射门结果,得出一个“真实威胁指数”

数据从哪来?常见足球数据字段与含义

想要做边路对比分析,通常需要两类数据:

  • 事件数据(Event Data):包含每个动作的类型(传球、带球、抢断)、坐标(x,y)、球员ID、时间戳,比如StatsBomb或Wyscout都提供公开样例数据。
  • 跟踪数据(Tracking Data):每秒25帧记录所有球员位置,但通常付费且处理复杂,初学者建议先用事件数据。

核心字段举例:

  • event_type:Dribble(带球)、Pass(传球)、Cross(传中)
  • position:坐标点,通常0~1归一化,例如x=0.8,y=0.1代表靠近右侧底线。
  • outcome:complete(成功)、incomplete(失败)
  • side:left/right/center(用于区分左右路)

核心指标拆解:不是只有“过人次数”那么简单

要公平对比两支队伍的边路突破能力,至少需要以下五个维度:

指标 含义 为什么重要
深度推进次数 带球或传球使球从对方半场推进到进攻三区(x>0.75)的次数 突破的核心价值在于“把战线压上去”
过人成功率(限制在对方半场) 过滤掉后场无意义花活 避免“无效盘带”
传中威胁值 传中找到禁区内队友的成功次数 + 导致射门的传中 光能突破但不形成射门等于零
突破速度 单位时间内的带球距离移动(米/秒) 速度决定防守是否重组
失误率(丢失球权) 被断球或传球失误 高失误突破是双刃剑

用Python你可以轻松写一个函数,把原始事件转换成上述指标,下面看实际案例。

Python实战案例:两支球队边路突破对比全流程

1 数据清洗与筛选(左/右边路事件提取)

假设我们有两支球队 Team_ATeam_B 的比赛事件数据,存储在Pandas DataFrame df_all里,先筛选左右边路事件:

import pandas as pd
# 假设事件坐标0~1,球场从左向右进攻,x表示纵向推进,y表示横向(0=左边线,1=右边线)
def classify_side(row):
    if row['y'] < 0.3:
        return 'left'
    elif row['y'] > 0.7:
        return 'right'
    else:
        return 'center'
df_all['side'] = df_all.apply(classify_side, axis=1)
# 只看进攻三区事件(对方半场纵坐标>0.6,假设球队从x=0向左进攻,则进攻方向为x增大)
# 注意:真实数据中需要根据上下半场调换方向,此处简化
df_attack = df_all[(df_all['x'] > 0.6) & (df_all['side'].isin(['left','right']))]

2 计算核心指标

接着计算每队的左侧、右侧突破关键指标:

result = []
for team in ['Team_A', 'Team_B']:
    for side in ['left', 'right']:
        subset = df_attack[(df_attack['team'] == team) & (df_attack['side'] == side)]
        # 带球尝试次数
        dribbles = subset[subset['event_type'] == 'dribble']
        complete_dribbles = dribbles[dribbles['outcome'] == 'complete']
        # 传中威胁:传中成功且落点在小禁区(假设有target_x>0.85且target_y在禁区范围)
        crosses = subset[subset['event_type'] == 'cross']
        dangerous_crosses = crosses[crosses['target_x'] > 0.85]
        # 深度推进:任何导致x坐标净增加>0.15的事件
        deep_prog = subset[subset.apply(lambda r: r.get('end_x', r['x']) - r['x'] > 0.15, axis=1)]
        result.append({
            'team': team,
            'side': side,
            'dribble_success_rate': len(complete_dribbles) / max(len(dribbles), 1),
            'deep_progressions': len(deep_prog),
            'dangerous_crosses': len(dangerous_crosses)
        })
df_summary = pd.DataFrame(result)
print(df_summary)

假设输出结果:

     team    side  dribble_success_rate  deep_progressions  dangerous_crosses
0  Team_A    left                 0.68                  12                 4
1  Team_A   right                 0.55                   8                 2
2  Team_B    left                 0.71                   9                 5
3  Team_B   right                 0.42                   6                 1

3 可视化对比:雷达图 + 热区图 + 时序流

(1)雷达图——多维度对比

我们定义四个评分维度:推进效率(deep_prog/全场进攻次数)、传中威胁右路活跃度左路活跃度

import matplotlib.pyplot as plt
import numpy as np
from math import pi
# 构造评分数组(0~1归一化)
labels = ['Deep Prog', 'Cross Threat', 'Right Act.', 'Left Act.']
# Team_A 示例分数
A_scores = [0.8, 0.6, 0.7, 0.9]  
# Team_B 示例分数
B_scores = [0.65, 0.75, 0.5, 0.85]
angles = np.linspace(0, 2 * np.pi, len(labels), endpoint=False).tolist()
A_scores += A_scores[:1]
B_scores += B_scores[:1]
angles += angles[:1]
fig, ax = plt.subplots(figsize=(6,6), subplot_kw=dict(polar=True))
ax.plot(angles, A_scores, 'o-', label='Team_A', color='#d62728')
ax.fill(angles, A_scores, alpha=0.25, color='#d62728')
ax.plot(angles, B_scores, 'o-', label='Team_B', color='#1f77b4')
ax.fill(angles, B_scores, alpha=0.25, color='#1f77b4')
ax.set_xticks(angles[:-1]); ax.set_xticklabels(labels)
ax.legend(loc='upper right'); plt.show()

雷达图清晰显示:A队左路推进更强,但传中威胁不如B队;B队右路相对薄弱,左路全面占优

(2)热区图——看边路推进发生的准确位置

使用scatter或hexbin展示两队有效的带球推进起始坐标:

plt.figure(figsize=(10,5))
for idx, team in enumerate(['Team_A','Team_B']):
    plt.subplot(1,2,idx+1)
    team_events = df_attack[(df_attack['team']==team) & (df_attack['side']=='right')]
    plt.hexbin(team_events['x'], team_events['y'], gridsize=15, cmap='Blues')
    plt.title(f'{team} Right-side progression heatmap')
    plt.axis('off')
plt.tight_layout(); plt.show()

可以看到A队主要从深度区域(x=0.7~0.85)启动突破,而B队更多集中在边线贴身位置(y接近1)——说明B队依赖纯粹拉边的速度型边锋,A队更偏向肋部配合。

(3)时序流——看突破是否发生在关键比赛时段

按比赛分钟划分,统计每5分钟的边路过人尝试次数:

df_min = df_attack[df_attack['event_type']=='dribble'].copy()
df_min['minute_bin'] = (df_min['minute'] // 5) * 5
pivot = df_min.groupby(['team','minute_bin']).size().unstack(fill_value=0)
pivot.T.plot(kind='line', marker='o')
plt.xlabel('Match minute'); plt.ylabel('Dribble attempts (wide)')'Temporal Pattern of Wide Dribbles')
plt.show()

如果A队在75分钟后右路突破次数骤增,可能说明他们利用换人体能优势;如果B队下半场初段突然加强左路,可能是中场战术调整。

常见问题QA(问答环节)

Q1:只有公开的免费数据源,能完成这种分析吗? 答:完全可以,推荐 StatsBomb 的免费公开数据集(包含美洲杯、世界杯部分比赛),只需在GitHub上搜索 statsbomb open data 就有JSON格式事件文件,用Pandas的 json_normalize 可以导入,虽然字段不如商业数据丰富,但包含坐标和事件类型,足够做上述基础对比。

Q2:如果数据没有传中目标点的坐标怎么办? 答:退而求其次,你可以用“传中后的射门”作为代理指标,只要在传中事件的 5 秒内,同队有一次射门事件,就判定为有威胁传中,需要时间戳对齐,设定一个时间窗口(same_possession 字段),代码逻辑类似:

# 假设有 possession_id 字段
df_shot = df_all[df_all['event_type']=='shot']
threat_crosses = crosses.merge(df_shot[['possession_id']], on='possession_id', how='inner')

Q3:怎么避免“方向误导”?比如左边锋踢到右边路? 答:这是真实数据处理的坑,建议使用 player_position 或者更精确的 position 事件中的角色ID(例如21=左边锋,25=右边锋),但现代的战术体系允许左右互换,严谨做法是计算带球方向向量——从起点坐标指向终点坐标,当绝对值纵向分量(dx)> 0.1时,看dy是正(向右路)还是负(向左路),最终边路归属应以事件发生区域的横向坐标为主,球员固定位置为辅。

数据告诉你的,和教练看到的一样吗?

通过Python事件流分析,我们能得出如“A队右侧突破成功率低于左边,且传中威胁极低——建议释放右边锋内切换取左路更多支援”这样的结论,这比单纯说一句“A队边路进攻不错”要有说服力得多。

但要注意两个局限:

  1. 对手防守强度未标准化:对手A的左后卫比对手B的右后卫强,那么简单的成功率对比会含有偏差,进阶可以用“预期威胁模型”或加入对手防守站位密度。
  2. 数据无法体现无球跑动:边路的“拉开宽度”就算没有完成过人,也可能为中路创造空间,这种价值指标难以捕捉。

最好的方式是:用Python做定量筛选,再用视频回放做定性确认,数据告诉你“是什么”,教练解释“为什么”,两者结合,才是现代足球分析的正道。

抱歉,评论功能暂时关闭!