python案例如何结合xGA评估防守表现?

wen python案例 13

Python实战:如何用xGA(预期进球数)科学评估足球防守表现?

python案例如何结合xGA评估防守表现?


目录导读

  1. 为什么传统防守数据会“骗人”?
  2. xGA是什么?与xG、失球数的本质区别
  3. 数据准备:从Understat/FBref获取射门事件数据
  4. Python实现:三步计算球队xGA
    • 步骤1:射门质量映射(xG模型简化)
    • 步骤2:对手射门聚合与“防守压力修正”
    • 步骤3:滚动窗口平滑与可视化
  5. 案例实战:2023-24英超前6名防守质量对比
  6. 关键问答:xGA的陷阱与高级用法
  7. xGA如何改变球探与教练决策

为什么传统防守数据会“骗人”?

只看“失球数”评价防守,等于用结果倒推过程——门将超神时,后防漏洞被掩盖;门将失误时,整条防线背锅,更科学的做法是看对手获得了多少“预期进球”,即xGA(Expected Goals Against),一个让对手狂轰20脚但只丢1球的防线,与一个让对手只射5脚却丢2球的防线,谁更稳固?xGA告诉我们答案是后者——因为前者长期必然“还债”。

xGA是什么?与xG、失球数的本质区别

  • xG(预期进球):衡量单次射门的破门概率(0~1),基于射门距离、角度、身体部位、助攻类型等。
  • xGA(预期失球):把对手的所有射门xG值相加,就是该队防守端的“期望失球数”。
  • 失球数:实际结果,包含大量随机噪声(门将扑救、门柱、运气)。

核心逻辑:xGA剥离了门将表现和运气,纯粹衡量“防守体系给予对手的射门质量与数量”,xGA越低,说明防守体系越能限制对手创造高质量机会。

数据准备:从Understat/FBref获取射门事件数据

我们使用Python的requests + pandas抓取 Understat(免费、带xG数据)的每场比赛射门事件,示例数据源结构:

import pandas as pd
import requests
from io import StringIO
# 以英超某轮为例(实际需循环赛季所有比赛ID)
url = "https://understat.com/match/12345"
html = requests.get(url).content
# 解析JSON中的shotsData字段(此处省略正则提取)
df_shots = pd.read_json(StringIO(shots_json))  # 包含: xG, h_a(主/客), player, minute...

字段h_a(主/客)、xGresult(射正/进球/封堵)、shotType,我们只需保留“客队射门且主队为防守方”或反之。

Python实现:三步计算球队xGA

步骤1:射门质量映射(xG模型简化)

若数据源未直接给xG,可用简化模型:xG = 1/(1 + exp(-(−0.5 + 0.3*角度 + 0.7*距离系数))),但Understat已提供准确xG,直接用:

df_shots['xGA_for_defender'] = df_shots.apply(
    lambda row: row['xG'] if row['h_a'] != team_side else 0, axis=1)

步骤2:防守压力修正(高级技巧)

单纯求和等于“未考虑防守干扰”,引入射门前防守压迫权重:若射门发生前3秒内防守球员距离<1.5米,则xG乘0.7(高强度干扰),用追踪数据(如StatsBomb)或手动标记关键比赛:

def pressure_correction(row):
    if row['pressure_events'] > 0:  # 假字段
        return row['xG'] * 0.75
    return row['xG']

步骤3:滚动窗口平滑与可视化

xGA逐场噪声大,用5场滚动平均展示趋势:

df_team = df_shots.groupby(['match_id', 'defense_team'])['xG_adjusted'].sum().reset_index()
df_team['xGA_rolling'] = df_team.groupby('defense_team')['xG_adjusted'].transform(
    lambda x: x.rolling(5, min_periods=1).mean())

matplotlib绘制:横轴比赛轮次,纵轴滚动xGA,多条线对比。线越平稳且越低,防守越稳定

案例实战:2023-24英超前6名防守质量对比

我们抓取阿森纳、曼城、利物浦、维拉、纽卡、热刺的全部38轮射门数据并计算xGA,结果(示意,非真实数据):

  • 阿森纳:赛季总xGA 28.5,滚动曲线始终在1.2以下(强项:禁区中路人墙密集)。
  • 曼城:总xGA 31.2,但门将埃德森扑救导致实际失球仅26(xGA比失球高,说明门将“+2.0”)。
  • 利物浦:总xGA 33.8,但曲线在12-20轮冲高至1.8(中卫伤病潮),后几轮回落。

关键洞察:维拉xGA仅34.1,但实际失球41——门将马丁内斯连续失误造成“负防守”,这恰好被xGA揭露,而非责怪后卫。

关键问答:xGA的陷阱与高级用法

Q1:xGA能完全替代人眼录像分析吗? 不能,xGA量化“量”,但无法解释“为什么”——比如对手射门全部在禁区外,说明防守策略成功;若全部在小禁区,则需改变阵型。结合事件上下文(传球序列、跑动)才有意义。

Q2:如何用xGA评估球员个体防守? 需拆解“目标球员在防守时对手的射门xG”,中卫A在场时,对手xGA为0.9/90分钟;不在场时变1.3,说明A有显著贡献,但需控制对手强度(难度系数)。

Q3:xGA和失球数差异多少算“异常”? 统计上,赛季xGA与实际失球的差值绝对值>0.1/场,通常归因于门将,差值负得越多(实际失球远小于xGA),门将表现越超神,但下赛季大概率回归——这就是“xGA预测防守下滑”的依据。

Q4:如何考虑主场、红牌、对手少打一人? 必须做场景化修正,删除红牌后阶段的射门,或单独计算“11v11”的xGA,否则,一张红牌毁掉整队数据。

xGA如何改变球探与教练决策

  • 教练:用xGA定位防守体系的真空地带(如右侧肋部),针对性布置低位防守或压迫方向。
  • 球探:识别“被低估防守球员”——真实xGA远优于媒体评分,这类中卫或后腰转会性价比极高。
  • 球迷:不再怒吼后卫失误,而是理解是体系允许了高xG射门。

最后提醒:xGA不是万能标尺,但它结合Python自动化处理,让我们从“看比分”进化到“看模型”。当你看到一支球队xGA极低却连续丢球,别急着骂门将——先检查是不是自己的样本量太小,用滚动窗口+压力修正后的xGA,才敢说“防守硬度”这四个字。


:本文所有数据抓取代码需遵守目标网站robots.txt,仅用于学习研究,实际项目中建议使用API或授权数据库(如StatsBomb、Opta)。

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