本文目录导读:

这是一个非常专业且务实的问题,在足球分析领域,xGA(预期失球数) 本身是衡量“防守结果”的指标,但要评估真正的“防守表现”,我们需要将它与对手的射门质量、防守行为以及门将扑救结合起来。
单纯看xGA高低会有误导性(对手狂轰滥炸但xGA值很高,说明防守体系被击穿;对手传中满天飞但xGA很低,说明防守限制做得好)。
以下是一个结合实用脚本(Python/Pandas)的评估防守表现的逻辑框架和代码思路。
核心维度拆解
要评估防守表现,我们不能只看一个xGA数,需要拆解为以下四个核心维度:
- 限制对手射门数量(Volume):对手射门总数(npxG,即排除点球的射门)。
- 限制对手射门质量(Quality):对手平均每次射门的xG值(xG per Shot),这反映了防守是否让对手在低威胁区域起脚。
- 高位压迫与拦截(Disruption):PPDA(每次防守行动允许对手传球次数)、抢断数、拦截数,这反映了防守的主动性。
- 门将的表现(Goalkeeping):xGA与失球数(GA)的差值(PSxG-GA,即门将扑救预期与失球差),这用来剔除门将超神/超鬼对防守数据的污染。
实用脚本设计(Python示例)
假设我们有一份比赛事件数据(如StatsBomb或Wyscout格式),我们编写一个脚本来综合评估。
第一步:数据预处理与基础指标计算
import pandas as pd
import numpy as np
# 假设 df 是包含所有射门事件的DataFrame
# 字段:team(进攻方)、opponent(防守方)、shot_type(射门类型)、xG(该次射门的xG)、
# location(位置)、body_part(身体部位)、assist_type(助攻类型)
# home_team, away_team, season
# --- 1. 计算防守方的 xGA(即进攻方的总xG) ---
def calculate_xga(df):
# 筛选所有射门事件(排除点球)
shots = df[df['shot_type'] != 'Penalty'].copy()
# 按比赛和防守方聚合
xga_data = shots.groupby(['match_id', 'opponent']).agg(
opponent_shots=('xG', 'count'), # 对手射门数
xga_total=('xG', 'sum') # 总xGA
).reset_index()
# 计算每次射门的平均质量 (xG per Shot)
xga_data['xG_per_shot'] = xga_data['xga_total'] / xga_data['opponent_shots']
return xga_data
# --- 2. 限制性防守指标 (PPDA - 每次防守行动允许传球数) ---
# 需要传球数据和防守动作数据
def calculate_ppda(passes, defensive_actions):
# 防守动作:抢断、拦截、犯规
actions = defensive_actions[defensive_actions['type'].isin(['Tackle', 'Interception', 'Foul'])].copy()
# 只统计对方后场2/3区域的防守动作(高位压迫指标)
# 假设球场的x坐标是0-100,这里仅算示例
actions['high_press'] = np.where(actions['x'] > 60, 1, 0) # 示例阈值
# 计算每个队的PPDA
ppda_data = passes.groupby(['match_id', 'team']).size().reset_index(name='allowed_passes')
action_data = actions.groupby(['match_id', 'team']).size().reset_index(name='def_actions')
# 合并
ppda_df = ppda_data.merge(action_data, left_on=['match_id', 'team'], right_on=['match_id', 'team'])
ppda_df['PPDA'] = ppda_df['allowed_passes'] / ppda_df['def_actions']
return ppda_df
第二步:引入门将表现(PSxG - 射正后预期失球)
这一步非常关键,我们要把门将的扑救从防守体系中剥离出来。
# --- 3. 门将表现评估 (PSxG vs GA) ---
import json
def calculate_gk_performance(events):
"""
计算门将数据。
PSxG 是射正后的预期进球,GA 是实际失球。
PSxG - GA 为正值说明门将表现低于预期(丢球过多),负值说明门将表现超出预期。
"""
# 筛选射正且导致进球或扑救的事件
goal_events = events[(events['shot_outcome'] == 'Goal') & (events['shot_type'] == 'Penalty')]
# 注意:我们需要更精细的数据,这里简化
psxg_data = events[['match_id', 'team']].drop_duplicates()
# 假设有一个 column: psxg 和 goals_conceded
gk_stats = events.groupby(['match_id', 'team']).agg(
psxg=('psxg', 'sum'),
goals_conceded=('goals_conceded', 'sum') # 如果是防守方视角
).reset_index()
gk_stats['gk_diff'] = gk_stats['psxg'] - gk_stats['goals_conceded']
return gk_stats
第三步:综合评分模型(核心)
这个脚本的核心是将上述指标压缩成一个可视化的“防守强度评分”。
# --- 4. 防守表现综合评估函数 ---
def evaluate_defensive_performance(xga_df, ppda_df, gk_df, team_name):
"""
结合xGA、射门限制、压迫强度、门将表现,输出防守画像。
"""
team_xga = xga_df[xga_df['team'] == team_name]
team_ppda = ppda_df[ppda_df['team'] == team_name]
team_gk = gk_df[gk_df['team'] == team_name]
# 计算加权得分(基础版)
# 1. 控制对手射门质量得分(越低越好)
# 这里假设所有值都是按赛季平均标准化
league_avg_xg_per_shot = xga_df['xG_per_shot'].mean()
league_std_xg_per_shot = xga_df['xG_per_shot'].std()
# 转为Z-score(标准分数)
z_xg_per_shot = (team_xga['xG_per_shot'].mean() - league_avg_xg_per_shot) / league_std_xg_per_shot
# Z-score越低,防守越好(因为限制对手射门质量好)
quality_score = -z_xg_per_shot # 取负值,让“限制性好”变成正分
# 2. 压迫指标得分(PPDA越低越好,代表逼抢越凶)
league_avg_ppda = ppda_df['PPDA'].mean()
league_std_ppda = ppda_df['PPDA'].std()
z_ppda = (team_ppda['PPDA'].mean() - league_avg_ppda) / league_std_ppda
pressure_score = -z_ppda
# 3. 门将表现得分(gk_diff为负值代表门将发挥好,或者忽略门将,看防守体系本身)
# 注意:评估防守体系时,通常用“镜前xGA”而不是“实际失球”,
# 所以我们应该看“门将面对的期望失球”减去“门将实际丢球”。
# 如果门将表现好(PSxG-GA为正),说明防守体系其实没那么好,但门将兜底了。
# 为了评估防守表现,我们更关注“非门将因素”,即 xGA - PSxG。
# 这其实是“防守体系让门将面临什么样质量的射门”。
# 这里简化为输出防守体系xGA的原始值大小
overall_xga_rating = team_xga['xga_total'].mean()
# 输出结果
print(f"球队: {team_name}")
print(f" 🎯 对手射门质量 (xG/Shot): {team_xga['xG_per_shot'].mean():.3f} (联赛均值: {league_avg_xg_per_shot:.3f})")
print(f" 🧤 压迫强度 (PPDA): {team_ppda['PPDA'].mean():.2f} (越低越激进)")
print(f" 🥅 场均xGA: {overall_xga_rating:.2f}")
print(f" 📊 综合防守评分: {quality_score + pressure_score:.2f} (正数表示优于联赛平均)")
return {
'team': team_name,
'xGA_per_match': overall_xga_rating,
'opp_shot_quality': team_xga['xG_per_shot'].mean(),
'PPDA': team_ppda['PPDA'].mean(),
'defensive_index': quality_score + pressure_score
}
进阶:可视化雷达图脚本
这是比较直观的展示方式,方便快速对比。
import matplotlib.pyplot as plt
import math
def plot_defensive_radar(team_stats, league_averages):
"""
team_stats: 目标球队的各项指标
league_averages: 联赛平均值
"""
categories = ['限制射门质量', '低位防守密度', '高位压迫强度', '人盯人执行力', '反抢效率']
# 计算各项指标的相对水平 (0-1)
# 注意:有些指标越小越好(如xG per Shot),有些越大越好(如拦截数)
values = [
min(team_stats['opp_shot_quality'] / league_averages['opp_shot_quality'], 1) * 100, # 质量限制
# 其他维度类似...
min(team_stats['xGA_per_match'] / league_averages['xGA_per_match'], 1) * 100,
# ...
]
# 绘制雷达图
angles = np.linspace(0, 2 * np.pi, len(categories), endpoint=False).tolist()
values += values[:1] # 闭合图形
fig, ax = plt.subplots(figsize=(6, 6), subplot_kw=dict(polar=True))
ax.fill(angles, values, color='blue', alpha=0.25)
ax.set_xticks(angles[:-1])
ax.set_xticklabels(categories)
plt.title('防守表现雷达图')
plt.show()
核心分析逻辑总结
在实际分析中,评估防守表现时,建议遵循以下数据链路:
- 看总量(xGA):确认防守体系是否容易被射门。
- 看质量(xG per Shot):确认防守是让对手“远射碰运气”还是“单刀直入”。防守好的球队通常能把对手xG/Shot压在0.10以下(联赛均值一般在0.10-0.12)。
- 看压迫(PPDA):确认防守是主动出击还是被动挨打。
- 扣掉门将(PSxG):如果一支球队xGA很高,但丢球很少,这可能是门将神勇,而非防守出色,反之,如果xGA很低,但失球很多,说明门将拖累了防守数据。
实用脚本的适用场景
- 球探报告:评估对手防守风格(是低位铁桶阵还是高位逼抢)。
- 个人表现:评估“防线球员”而不包括门将的贡献。
- 战术调整:通过对比xGA和PPDA,找出“高压被过”或者“低位防不住远射”的具体问题。
如果你有具体的数据格式(例如是Wyscout JSON还是StatsBomb JSON),我可以帮你写出更精确的清洗和聚合代码,你目前拿到的数据主要包含哪些字段?
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播