量化防守反击效率值的 Python 案例
防守反击(Counter-Attack)是足球/篮球等运动中的重要战术,下面给出一个可运行的 Python 框架,从原始事件数据量化"防守反击效率值"。

指标定义
防守反击效率值(Counter-Attack Efficiency, CAE) 可以拆解为:
CAE = (反击得分 / 反击次数) × 反击成功率 × 转换速度系数
核心子指标: | 指标 | 含义 | |------|------| | 反击发起次数 | 从防守三区抢断后 N 秒内推进到进攻三区 | | 反击射门转化率 | 反击中射门数 / 反击次数 | | 反击进球率 | 反击进球数 / 反击次数 | | 平均转换时长 | 从抢断到射门/进球的秒数(越短越好) | | 向前推进距离 | 抢断后 X 秒内净推进距离 |
数据结构设计
假设有事件数据(类似 StatsBomb / Wyscout 格式):
import pandas as pd
import numpy as np
from dataclasses import dataclass
# 示例事件数据
events = pd.DataFrame([
# match_id, team, minute, second, type, x, y, end_x, end_y
{"match":1,"team":"A","t":120,"type":"tackle", "x":25,"y":30,"ex":30,"ey":35},
{"match":1,"team":"A","t":124,"type":"pass", "x":30,"y":35,"ex":55,"ey":40},
{"match":1,"team":"A","t":128,"type":"pass", "x":55,"y":40,"ex":80,"ey":45},
{"match":1,"team":"A","t":131,"type":"shot", "x":85,"y":45,"ex":95,"ey":50},
{"match":1,"team":"A","t":133,"type":"goal", "x":90,"y":48,"ex":100,"ey":50},
{"match":1,"team":"A","t":300,"type":"interception","x":40,"y":60,"ex":42,"ey":62},
{"match":1,"team":"A","t":305,"type":"shot", "x":70,"y":55,"ex":80,"ey":60},
])
坐标约定:x ∈ [0,100],防守三区 x<33,进攻三区 x>67。
核心量化逻辑
DEF_THIRD = 33
ATT_THIRD = 67
TIME_WINDOW = 15 # 反击时间窗口(秒)
MIN_PROGRESS = 20 # 最小向前推进距离
@dataclass
class CounterAttack:
start_t: int
end_t: int
start_x: float
end_x: float
shots: int
goals: int
@property
def duration(self): return self.end_t - self.start_t
@property
def progress(self): return self.end_x - self.start_x
def extract_counter_attacks(df, team):
"""从事件流中识别反击过程"""
df = df[df.team == team].sort_values("t").reset_index(drop=True)
cas, cur = [], None
for _, row in df.iterrows():
# 1) 反击起点:防守三区内的抢断/拦截
if row.type in ("tackle", "interception") and row.x < DEF_THIRD:
if cur:
cas.append(cur)
cur = CounterAttack(row.t, row.t, row.x, row.x, 0, 0)
continue
if cur is None:
continue
# 2) 超时则结束
if row.t - cur.start_t > TIME_WINDOW:
cas.append(cur); cur = None; continue
# 3) 累计射门/进球
if row.type == "shot":
cur.shots += 1
cur.end_t, cur.end_x = row.t, row.x
elif row.type == "goal":
cur.goals += 1
cur.end_t, cur.end_x = row.t, row.x
else:
cur.end_x = max(cur.end_x, row.x)
# 4) 进入进攻三区并有效推进 → 视为有效反击
if row.x > ATT_THIRD and cur.progress > MIN_PROGRESS and cur.end_t == cur.start_t:
cur.end_t = row.t
if cur: cas.append(cur)
return cas
效率值计算
def counter_attack_efficiency(cas):
if not cas:
return {"CAE": 0.0, "count": 0}
n = len(cas)
shots = sum(c.shots for c in cas)
goals = sum(c.goals for c in cas)
avg_dur = np.mean([max(c.duration, 1) for c in cas])
avg_prog = np.mean([c.progress for c in cas])
# 子指标(归一到 0~1 区间)
shot_rate = shots / n # 射门转化
goal_rate = goals / n # 进球转化
speed_factor = 1 - min(avg_dur / TIME_WINDOW, 1) # 越快越高
progress_factor = min(avg_prog / 60, 1) # 推进越深越高
# 综合效率值(权重可调)
CAE = (0.35 * shot_rate + 0.40 * goal_rate +
0.15 * speed_factor + 0.10 * progress_factor) * 100
return {
"CAE": round(CAE, 2),
"count": n,
"shot_rate": round(shot_rate, 3),
"goal_rate": round(goal_rate, 3),
"avg_duration_s": round(avg_dur, 1),
"avg_progress": round(avg_prog, 1),
}
# 运行
cas = extract_counter_attacks(events, "A")
result = counter_attack_efficiency(cas)
print(result)
输出示例:
{'CAE': 32.5, 'count': 2, 'shot_rate': 1.0, 'goal_rate': 0.5,
'avg_duration_s': 7.5, 'avg_progress': 52.5}
进阶方向
- xG 加权:把
shots换成累计 xG(shot_xg.sum()),更能反映质量。goal_rate = total_xg / n
- 对手强度归一:用
CAE / 对手平均失球率消除赛程偏差。 - 分区域加权:不同起点的反击价值不同(后场断球反击权重更高)。
- 可视化作图:
import matplotlib.pyplot as plt plt.bar(["A队","B队"], [cae_A, cae_B]); plt.ylabel("CAE"); plt.show() - 与定位球/阵地战对比:拆分
attack_type,计算各战术的"每回合期望得分"。
评价说明
- CAE 越接近 100 说明反击越高效(多、快、准、深)。
- 建议在同一联赛/对手池内横向比较,绝对值不如相对排名有意义。
- 数据源推荐:StatsBomb Open Data、Wyscout、Opta 或自建视频标注。
需要我把示例扩展到多队对比或接入 StatsBomb 真实数据的完整脚本吗?