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

wen python案例 1

Python案例:如何结合xGA评估防守表现——从数据清洗到可视化全流程解析

目录导读

  1. xGA是什么?为什么防守评估必须用它?
  2. 数据准备:从StatsBomb/FBref获取高质量事件数据
  3. Python实战:xGA模型构建核心逻辑(含代码)
  4. 防守表现评估框架:超越“丢球数”的四个维度
  5. 可视化与报告:用雷达图+时间序列讲清防守故事
  6. 常见问题QA:xGA计算中的陷阱与规避

xGA是什么?为什么防守评估必须用它?

xGA(Expected Goals Against,预期失球)是衡量防守质量的核心进阶指标,它通过场上射门位置、角度、助攻方式、防守压力等变量,计算每次射门的进球概率,累计后得到“一支球队本应丢多少球”的基准值。

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

为什么传统“失球数”不够用?

  • 失球数受随机性影响大(门将神扑 vs 对方打飞)。
  • 无视射门质量——对手30米远射和单刀都被记为“1次丢球”。
  • 无法区分后卫线与门将的单独贡献。

xGA的核心洞察:
若球队实际失球(GA)远高于xGA,说明防守存在结构性漏洞(如禁区内漏人)或门将状态低迷;反之则可能防守韧性极强或运气极佳。


数据准备:从StatsBomb/FBref获取高质量事件数据

评估防守,最理想的是带坐标的事件流数据
推荐免费API:StatsBomb开放数据(含英超、西甲、女足世界杯等),或使用worldfootballR包回调FBref的进阶防守统计。

数据字段必须包含:

  • shot.outcome(进球/扑救/被封堵/射偏)
  • location(射门坐标,以球门中心为原点)
  • under_pressure(是否受压迫)
  • assist_type(直塞/传中/定位球)
  • 防守方事件(拦截、抢断、解围、犯规区域)

用Python拉取StatsBomb示例:

import pandas as pd
from statsbombpy import sb
# 拉取2020欧洲杯比赛事件
df = sb.events(match_id=3788741)  # 替换为真实比赛ID
shots = df[(df['type']=='Shot') & (df['shot']['type']=='Open Play')]

Python实战:xGA模型构建核心逻辑

1 特征工程(防守视角的关键变量)

目标变量:射门是否转化为进球(1/0)。
特征建议:

  • 射门距离球门中心(hypot(dx, dy)
  • 射门角度(atan2(y, x)
  • 射门部位(脚/头)
  • 是否受压迫(1或0)
  • 进攻方式(运动战/定位球/反击)

2 训练XGBoost模型(代码精简版)

from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import log_loss
# 已清洗的shots_df包含['distance','angle','pressure','header']
X = shots_df[['distance','angle','pressure','header']]
y = shots_df['goal']
# 用Logistic回归作为baseline
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression().fit(X, y)
# 用XGBoost提升非线性拟合能力
xgb = XGBClassifier(n_estimators=300, max_depth=3, eta=0.05)
xgb.fit(X, y)
# 预测每脚射门的xG值
shots_df['xG'] = xgb.predict_proba(X)[:,1]

3 球队xGA聚合

按每场比赛的对手射门事件,分别加总射门方的xG,即为该队的xGA:

xga_table = shots_df.groupby(['match_id','defending_team'])['xG'].sum()

防守表现评估框架:超越“丢球数”的四个维度

阻止射门产生(对应“xGA总量”)

  • 联赛中高xGA并不全是坏事——如曼城xGA低但防线前提,需结合“对手射门数”分析。

限制射门质量(对应“平均射门xG值”)

用Python求:每场对手射门的平均xG,若低(如0.08),说明防守让对手只能远射或低角度进攻。

门将表现(GAA + PSxG差)

通过post_shot_xg(射门后的预期值)对比门将实际扑救:

# 统计门将的实际失球 vs 对方射门的xG总和
goalkeeper_diff = actual_goals_conceded - sum_opponent_xg

负数越大代表门将扑救超常。

防守韧性(高xGA比赛中的抢分能力)

用Python计算“高xGA(>1.5)比赛的拿分率”,评估逆风防守时的战术执行成功率。


可视化与报告:用雷达图+时间序列讲清防守故事

1 雷达图对比球队防守维度(示例)

制作雷达图核心代码

import plotly.express as px
# 假设包含: 场均xGA, 对手射门数, 对手平均射门xG, 高威胁球比例, 门将扑救率
fig = px.line_polar(data, r=values, theta=labels, line_close=True)

2 时间序列:xGA vs 实际失球随比赛轮次变化

import matplotlib.pyplot as plt
plt.plot(matchday, xga_per_match, label='xGA')
plt.plot(matchday, actual_goals, alpha=0.7, label='GA')
plt.axhline(0, color='grey', lw=0.8)

3 热力图定位防守薄弱区域

过滤对手射门未进球但xG>0.3的事件,用hexbin绘制禁区危险区高亮。


常见问题QA:xGA计算中的陷阱与规避

Q1:直接用进球数当y标签,会不会数据太稀疏?
会,每场比赛每队约10-15脚射门,进球仅1-3个,建议使用更大数据集(跨赛季),或使用平滑技巧,如训练光线GBM+负采样。

Q2:防守压力的变量如何标准化?
不同数据源(StatsBomb vs 手动影片)对“压力”定义不一致,可用距离最近防守者的距离(米)来客观度量,而非0/1标记。

Q3:xGA能评估无球跑动和站位吗?
间接评估,若对手传球前已构成高威胁,xGA会高,但纯战术阻断传球路线,需结合防守对抗热力图。

Q4:为什么我的xGA模型精度低?
绝大多数xG模型AUC在0.7-0.8,该指标用于评估防守相对值够用,但不用预测单次射门结果。

Q5:如何给球探报告使用?
输出按对手射门位置拆分的xGA贡献,配合“丢失球权区域”叠加可视化定位人盯人问题。


结合Python进行xGA防守评估,本质是将防守方的“允许对方射门质量”用数据量化为可迭代指标,先建立可靠的xG射门评分器,再按比赛聚合防守数据,最终通过指标差异识别问题球员或战术苗头。

建议开发者用StatsBomb的免费数据+scikit-learn构建初始版,半年后回测自己的预测准确性,再引入更复杂的时空模型。xGA永远是对比工具,而不是绝对真理——它帮你发现需要深挖的比赛片段,然后回归录像分析才是落地。

如果你希望从零开始构建一个真实赛季的防守评估看板,从清洗坐标、特征到部署FastAPI API,下一期可以拆解完整工程实现。

上一篇python案例认为直接任意球得分概率多大?

下一篇当前分类已是最新一篇

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