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

wen python案例 2

Python实战:如何结合xGA(预期失球)量化评估球员防守表现?——从数据清洗到可视化全流程解析

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


目录导读

  1. 为什么传统防守数据“骗人”?——xGA的诞生逻辑
  2. 数据准备:你需要哪些字段?(附样例数据集结构)
  3. Python实战:构建xGA防守贡献模型的5个核心步骤
    • 1 特征工程:从对手射门到防守压力权重
    • 2 模型选择:xgboost vs. 泊松回归的取舍
    • 3 评估指标:如何用“防守xGA差值”排名?
  4. 可视化:用雷达图+热力图讲出防守故事
  5. 常见陷阱与解决方案(附问答环节)
  6. 从“看数据”到“用数据决策”

为什么传统防守数据“骗人”?——xGA的诞生逻辑

传统防守统计(如抢断数、解围数)往往与球队的控球率、对手风格强相关,一个高位逼抢球队的后卫抢断数必然高于低位防守队,但这并不代表他防守更好。xGA(Expected Goals Against,预期失球) 通过量化“每次射门转化为进球的概率”,结合射门位置、角度、助攻类型、防守压迫度等变量,计算出球员在场时对手的“合理进球数”,防守者的核心价值在于将对手的xGA压制到低于联盟平均水平

数据准备:你需要哪些字段?(附样例数据集结构)

我们采用公开的英超2023-2024赛季事件流数据(模拟结构):

字段名 类型 说明
player_id str 防守球员唯一ID
opposition_shot_x float 对手射门的标准化横坐标(0-1)
opposition_shot_y float 纵坐标
shot_angle float 射门角度(弧度)
shot_body_part str 头/脚/其他
pressure_events int 防守球员在该次射门前的压迫次数
distance_to_ball float 射门瞬间防守者与球的距离(米)
is_goal int 是否进球(0/1)

关键点:xGA模型需要对手射门样本而非自己的防守动作样本,每个防守球员的“防守片段”定义为他参与防守(如距离球30米内)时的对手射门事件。

Python实战:构建xGA防守贡献模型的5个核心步骤

1 特征工程:从对手射门到防守压力权重

import pandas as pd
import numpy as np
from scipy.stats import gaussian_kde
# 读取事件数据
df = pd.read_csv('pl_events.csv')
# 特征1:角度特征(越大越危险)
df['angle_deg'] = np.degrees(df['shot_angle'])
# 特征2:距离-压力复合特征
df['pressure_score'] = df['pressure_events'] / (df['distance_to_ball'] + 0.5)
# 特征3:射门位置密度(历史进球密度)
kde = gaussian_kde(df[df['is_goal']==1][['opposition_shot_x','opposition_shot_y']].T)
df['shot_density'] = kde.evaluate(df[['opposition_shot_x','opposition_shot_y']].T)

2 模型选择:xgboost vs. 泊松回归的取舍

  • 泊松回归:假设进球服从泊松分布,可解释性强,但难以捕捉非线性交互(如角度+距离的协同效应)。
  • XGBoost:能自动学习特征交互,通常提升AUC 5-8%,这里我们采用XGBoost(梯度提升树)作为主力模型:
from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
features = ['angle_deg', 'distance_to_ball', 'shot_density', 'pressure_score']
X = df[features]
y = df['is_goal']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
model = XGBClassifier(n_estimators=300, max_depth=5, learning_rate=0.05)
model.fit(X_train, y_train, eval_set=[(X_test, y_test)], early_stopping_rounds=30, verbose=False)
# 输出每个样本的预期失球概率,即xGA值
df['xGA'] = model.predict_proba(X)[:, 1]

3 评估指标:如何用“防守xGA差值”排名?

核心公式
防守贡献 = 球员在场时的每90分钟实际失球 - 球员在场时的每90分钟xGA总和
如果为负值,说明该球员“阻止了预期进球”,防守贡献为正。

player_stats = df.groupby('player_id').agg(
    total_xGA = ('xGA', 'sum'),
    total_goals = ('is_goal', 'sum'),
    minutes = ('minutes', 'sum')  # 需要额外字段
)
player_stats['xGA_90'] = player_stats['total_xGA'] / player_stats['minutes'] * 90
player_stats['GA_90'] = player_stats['total_goals'] / player_stats['minutes'] * 90
player_stats['defensive_contribution'] = player_stats['GA_90'] - player_stats['xGA_90']
# 排名前5的防守者
print(player_stats.sort_values('defensive_contribution', ascending=True).head(5))

可视化:用雷达图+热力图讲出防守故事

雷达图:展示防守者的多维度能力(拦截/压迫/清道)

import plotly.express as px
from math import pi
# 假设选取3位球员的6维特征
categories = ['抢断', '拦截', '头球解围', '压迫强度', '回追速度', 'xGA降低']
values = [85, 72, 90, 88, 95, 80]  # 示例
fig = px.line_polar(r=values, theta=categories, line_close=True, title='球星防守能力雷达图')
fig.show()

热力图:显示对手射门分布及被该球员防守后xGA的变化

import matplotlib.pyplot as plt
import seaborn as sns
# 分割防守区域网格
plt.figure(figsize=(8, 6))
hexbin = plt.hexbin(df['opposition_shot_x'], df['opposition_shot_y'], 
                     C=df['xGA'], gridsize=20, cmap='Reds', reduce_C_function=np.mean)
plt.colorbar(hexbin, label='平均xGA')'该球员防守区域预期失球热力图')
plt.xlabel('球场横向位置')
plt.ylabel('球场纵向位置')
plt.show()

常见陷阱与解决方案(附问答环节)

Q1:xGA模型是否应该区分门将和后卫?
A:建议分开建模,门将的动作特征(扑救反应)与后卫(压迫、封堵)差异极大,分别训练两个模型,再比较各自领域的xGA贡献。

Q2:小样本球队(如降级队)如何平滑数据?
A:使用贝叶斯分层模型(如PyMC)或引入“联盟先验”进行收缩估计,简单做法:将球员的xGA总和加上联盟平均的alpha值(正则化)。

Q3:如何避免位置偏差?(如边后卫面对的射门角度天然更大)
A:在特征中加入player_position(CB, LB, RB等)作为分类变量,让模型学习位置基线,或者计算“位置调整后的xGA”(Position-Adjusted xGA)。

Q4:实时防守数据能否做到?
A:可以,使用光流法或物体检测(如YOLO)追踪球员和球的位置,每100ms计算一次XGA,但需要极高质量且低延迟的跟踪数据源。

从“看数据”到“用数据决策”

通过Python结合xGA评估防守表现,我们突破了“抢断数”的表象,量化了防守者的真实“降险”价值,这套流程不仅适用于足球,也可迁移至篮球(防守投篮预期命中率)、冰球等场景,结合时序模型(LSTM)分析防守跑位轨迹,将是职业俱乐部数据分析团队的必备技能。


问答环节补充

  • :请问xGA与FT(射正率)有什么区别?

  • :FT只统计射正后进球的比例,忽略射偏、被阻挡等原因;xGA基于全量射门事件建模,包含射门质量参数,更全面。

  • :如何验证xGA模型的准确性?

  • :计算校准曲线(Brier Score),确保预测概率与真实进球率吻合;同时对比历史上相同场景的进球率(如位置+角度+压力),通常Brier Score低于0.14即视为优秀。


本文数据与代码基于公开模拟数据,实战中请确保数据源权威合规。

上一篇python案例认为泊松分布预测进球有效吗?

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

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