本文目录导读:

- 第一步:数据准备(假设你已有原始事件数据)
- 第二步:核心脚本逻辑(Python伪代码/思路)
- 第三步:如何“实用”地解读这份报告(关键)
- 第四步:进阶实战脚本——“防守贡献度”评估
- 第五步:将脚本用于实战决策
- 总结一句话
这是一个非常专业且切合现代足球分析潮流的话题,xGA(预期失球)的核心价值在于剥离门将表现和运气成分,评估对手射门机会的质量。
要“实用”,脚本必须解决一个核心矛盾:xGA是球队整体防守的结果,但防守是整体行为,仅仅看一个赛季的总xGA意义不大,关键是要看“xGA的构成”和“xGA的分布”。
以下是一个结合xGA评估防守的实用脚本框架,分为三个层级:数据清洗、核心指标计算、场景化输出。
第一步:数据准备(假设你已有原始事件数据)
你需要的数据字段通常包括:
match_id:比赛IDteam:防守方球队opponent:对手minute:分钟xG:该次射门的预期进球值(0.01~0.98)location:射门位置(X/Y坐标,用于判断禁区内/外)situation:射门场景(Open Play,From Corner,FastBreak,Penalty,Set Piece)body_part:射门部位(头球/脚射)assist_type:助攻方式(传中、直塞、定位球、无助攻)result:射门结果(Goal,Saved,Blocked,Off Target)
第二步:核心脚本逻辑(Python伪代码/思路)
实用的脚本不应该只输出一个数字,而应该输出“防守问题诊断报告”。
import pandas as pd
import numpy as np
def defensive_xga_report(df, team_name, min_minutes=500):
"""
生成针对特定球队的防守xGA诊断报告
"""
# 过滤出对手对该球队的射门数据
opp_shots = df[df['opponent'] == team_name].copy()
# --- 1. 基础总量指标 ---
total_xga = opp_shots['xG'].sum()
total_conceded = (opp_shots['result'] == 'Goal').sum()
# 防守端“超额失球” = 实际失球 - xGA (正数代表门将或运气差,负数代表门将神勇或防守封堵极佳)
delta = total_conceded - total_xga
# --- 2. 区域防守质量(最重要的实用指标) ---
# 利用坐标判断射门位置
# 假设坐标系:X轴 0-100(进攻方向),Y轴 0-100(宽度)
# 禁区中央"六码区" 或 点球点附近(高xG区)
high_danger = opp_shots[
(opp_shots['location_x'] > 85) & (opp_shots['location_y'] > 35) & (opp_shots['location_y'] < 65)
]
# 禁区内(非高危险区)
box_shots = opp_shots[opp_shots['location_x'] > 80] # 简化判断
# 禁区外远射
outside_box = opp_shots[opp_shots['location_x'] <= 80]
# 输出:不同区域的防守效率
report = {
'总xGA': round(total_xga, 2),
'实际失球': int(total_conceded),
'防守差值 (失球-xGA)': round(delta, 2),
'高危险区xGA占比': round(high_danger['xG'].sum() / total_xga * 100, 1) if total_xga > 0 else 0,
'禁区外远射xGA': round(outside_box['xG'].sum(), 2),
'场均被射门次数': round(len(opp_shots) / opp_shots['match_id'].nunique(), 1),
}
# --- 3. 定位球防守专项 ---
set_piece = opp_shots[opp_shots['situation'].isin(['From Corner', 'Set Piece', 'Free Kick'])]
open_play = opp_shots[opp_shots['situation'] == 'Open Play']
# --- 4. 防守“侵略性”指标(防守队员是否有效干扰) ---
# 这里需要数据中带有 blocked 状态
blocked_rate = (opp_shots['result'] == 'Blocked').mean()
# --- 5. 机会类型审查 ---
# 对手创造出的是“高xG的绝佳机会”还是“低xG的浪射”?
# 量化:xG 分布中位数和 P90(前10%的最危险射门)
top_chance = opp_shots['xG'].quantile(0.90)
report['定位球xGA'] = round(set_piece['xG'].sum(), 2)
report['运动战xGA'] = round(open_play['xG'].sum(), 2)
report['射门被封堵率'] = f"{blocked_rate * 100:.1f}%"
report['对手射门xG前10%分位数'] = round(top_chance, 2)
report['高危险区总xGA'] = round(high_danger['xG'].sum(), 2)
return report
第三步:如何“实用”地解读这份报告(关键)
脚本输出数据后,你需要结合进攻端的xG进行对比,才能得出防守水平的真实结论:
看“防守差值”(失球 vs xGA)
- 失球 < xGA(负数):
- 解读:球队防守端“超额表现”,要么是门将超神(如扑出高xG射门),要么是防守球员极限门线解围。
- 实战结论:这种防守不可持续,系统在下一赛季大概率回归均值,导致失球增多。不要因为战绩好就认为防守稳了。
- 失球 > xGA(正数):
- 解读:球队防守端“表现不佳”或运气极差。
- 实战结论:如果是短期(10场以内),可能是定位球漏人或者门将扑救失误导致,如果是长期,说明球队防对手反击或二点球存在严重心理或站位问题。
看“高危险区xGA占比”(核心中的核心)
- 比例高(>60%):对手很容易通过2-3脚传递打穿中场,直接面对中卫和后腰之间的真空地带(对手XG高达0.7的射门多)。说明球队的中场拦截和后卫回追速度存在缺陷,防线过于靠上。
- 比例低(<35%):对手被迫在禁区外远射,或者只能传中找低概率头球。说明球队防守阵型紧凑,低位防守有效,或者门将出击范围大,提前化解了高xG机会。
看“射门被封堵率”(防守积极性)
- 高封堵率(>30%):说明防守球员不惜体力,用身体挡枪眼,这是防守态度好的体现,但也常常伴随着吃牌风险和体能下降导致下半场崩盘,脚本应联动输出“下半场xGA vs 上半场xGA”进行验证。
看“定位球xGA” vs “运动战xGA”
- 如果定位球xGA超过总xGA的30%:说明防高空球和防抢点存在漏洞(例如盯人不紧,区域防守漏后点)。
- 如果运动战xGA高:则重点看对直塞球(Through Ball)的防守,特别是对手在快速转换中的射门(
FastBreak)xG值。
第四步:进阶实战脚本——“防守贡献度”评估
单纯看球队数据不够,实用脚本还应评估个体球员的防守贡献,这里有一个非常惊艳的用法:“门将扑救 vs 后卫防守”分离术。
def filter_defensive_efficiency(df, team_name):
"""
通过对比门将扑救前后xGA,评估后卫线的防守压力
"""
# 假设我们有门将扑救数据
shots_data = df[df['opponent'] == team_name].copy()
# 1. 射门发生时的xG(后卫允许对手射门的质量)
xg_before_save = shots_data['xG']
# 2. 门将实际扑救后,如果进球,则xG转化为1;如果扑出,则转化为0
# 这里我们需要一个简单的函数来计算门将的“扑救差”
# 3. 关键指标:被射正率 (SoT%)
# 这反映了后卫的干扰能力(如果后卫贴身,射门会偏出或被挡出)
sot_rate = shots_data[shots_data['result'].isin(['Goal', 'Saved'])].shape[0] / shots_data.shape[0]
# 4. 造越位战术的有效性(对手越位次数/射门次数)
# offside_data = df[df['event_type'] == 'Offside']
return {
'被射正率': f"{sot_rate*100:.1f}%",
'防守干扰指数 (1 - 被射正率)': f"{(1-sot_rate)*100:.1f}%"
}
第五步:将脚本用于实战决策
- 赛前准备:用脚本输出对手的进攻xG绘图分布,如果对手左路xG极高,则脚本应自动标注出防守方右后卫的防守压力区间。
- 引援研判:
- 如果你发现球队总xGA很低,但“高危险区xGA占比”极高,说明你需要一个防守型后腰(增加中场保护)。
- 射门被封堵率”极高,说明你需要一名高大中卫来“用脸挡球”,但要注意避免长期伤病。
- 战术调整验证:改变阵型后,对比最近5场与之前5场的场均xGA和场均被射正率,如果xGA下降,说明新阵型有效;如果xGA没变但失球减少,那大概率是门将爆发,不是战术功劳,别被战绩蒙蔽。
总结一句话
最实用的脚本逻辑:先把“总xGA”拆成“高威胁区xGA”和“低威胁区xGA”,再对比“实际失球”与“xGA”的差额,最后结合“被封堵率”判断防守的主动性。
如果脚本能输出这张热力图(X轴为射门位置,Y轴为xG值),那基本就无敌了,建议你在处理数据时优先将location_x和location_y做分层聚合(比如5x5米网格),这样能快速定位球队防守阵型中的“肋部空当”到底在哪里。