量化防守反击效率值的 Python 案例
防守反击(Counter-Attack)是足球、篮球等运动中重要的战术,下面我用足球为例,给出一个完整可运行的 Python 方案。

指标设计思路
防守反击效率 = 从抢断/拦截到射门的转化能力
核心公式:
反击效率值 = (反击形成的射门数 × 射门质量权重) / 反击发起次数 × 100
扩展维度:
| 维度 | 指标 | 权重示例 |
|---|---|---|
| 次数 | 反击发起次数 | |
| 质量 | xG(预期进球) | 5 |
| 速度 | 从抢断到射门秒数 | 2 |
| 推进 | 推进距离/传球数 | 2 |
| 结果 | 进球/射正 | 1 |
完整 Python 案例
准备数据(模拟一次比赛的反击事件)
import pandas as pd
import numpy as np
# 模拟一支球队的所有反击事件
data = [
# 反击ID, 起始方式, 起始时间(s), 射门时间(s), 推进距离(m), 传球数, xG, 是否射正, 是否进球
[1, "抢断", 120, 128, 45, 3, 0.15, 1, 0],
[2, "拦截", 300, 305, 30, 2, 0.08, 0, 0],
[3, "抢断", 540, 549, 60, 4, 0.35, 1, 1],
[4, "解围", 700, 703, 20, 1, 0.05, 0, 0],
[5, "抢断", 900, 908, 55, 3, 0.22, 1, 0],
[6, "拦截", 1100, 1112, 70, 5, 0.40, 1, 1],
[7, "抢断", 1300, 1302, 15, 1, 0.03, 0, 0],
[8, "抢断", 1500, 1512, 50, 4, 0.28, 1, 0],
]
df = pd.DataFrame(data, columns=[
"id", "start_type", "start_time", "shot_time",
"distance", "passes", "xG", "on_target", "goal"
])
# 派生:反击耗时
df["duration"] = df["shot_time"] - df["start_time"]
print(df)
归一化 + 计算效率值
def minmax(series):
return (series - series.min()) / (series.max() - series.min() + 1e-9)
# 速度分:耗时越短越好,用反向归一化
df["speed_score"] = 1 - minmax(df["duration"])
# 推进分:距离和传球综合
df["progress_score"] = 0.6 * minmax(df["distance"]) + 0.4 * minmax(df["passes"])
# 质量分:xG
df["quality_score"] = minmax(df["xG"])
# 结果分:进球>射正>无
df["result_score"] = df["goal"] * 1.0 + df["on_target"] * 0.5
# 综合单次反击效率(加权)
W = {
"quality_score": 0.4,
"speed_score": 0.2,
"progress_score":0.25,
"result_score": 0.15,
}
df["efficiency"] = sum(df[k] * w for k, w in W.items()) * 100
print(df[["id", "duration", "xG", "efficiency"]])
球队整体反击效率
def team_counter_efficiency(df, w=None):
"""
球队整体反击效率:
= 平均单次效率 × 转化率因子
转化率因子 = (射正率*0.5 + 进球率*0.5 + 1)
"""
avg_eff = df["efficiency"].mean()
on_target_rate = df["on_target"].mean()
goal_rate = df["goal"].mean()
conversion = 1 + on_target_rate * 0.5 + goal_rate * 0.5
total = avg_eff * conversion
return {
"反击次数": len(df),
"平均单次效率": round(avg_eff, 2),
"射正率": f"{on_target_rate:.0%}",
"进球率": f"{goal_rate:.0%}",
"综合反击效率值": round(total, 2),
}
result = team_counter_efficiency(df)
print(result)
输出示例:
{'反击次数': 8, '平均单次效率': 38.76, '射正率': 62%, '进球率': 25%, '综合反击效率值': 56.19}
进阶:对比两支球队
# 假设还有对手数据(略) # 用雷达图直观对比 import matplotlib.pyplot as plt labels = ["反击效率", "射正率", "进球率", "平均速度", "推进能力"] team_a = [56.2, 62, 25, 78, 65] team_b = [41.5, 45, 12, 60, 55] angles = np.linspace(0, 2*np.pi, len(labels), endpoint=False).tolist() angles += angles[:1] team_a += team_a[:1] team_b += team_b[:1] fig, ax = plt.subplots(figsize=(6,6), subplot_kw=dict(polar=True)) ax.plot(angles, team_a, label="主队", linewidth=2) ax.fill(angles, team_a, alpha=0.25) ax.plot(angles, team_b, label="客队", linewidth=2) ax.fill(angles, team_b, alpha=0.25) ax.set_xticks(angles[:-1]); ax.set_xticklabels(labels) ax.legend(loc="upper right")"防守反击效率对比") plt.show()
关键设计要点
- 起点定义要统一:抢断、拦截、解围、门将发球都可作为反击起点,需事先约定。
- 时间窗口:一般 15 秒内形成射门才算"反击",超过则归为阵地战。
- 权重可调:根据战术风格调整,比如速度快权重高。
- 归一化避免量纲差异:xG(0~1)、距离(0~100m)、时间(秒) 必须归一化。
- 样本量:单场数据波动大,建议用赛季累计数据。
真实数据接入建议
- StatsBomb Open Data:免费,含事件级坐标和时间
from statsbombpy import sb events = sb.events(match_id=3788741)
- FBref:有 xG、射门等统计
- WhoScored / Opta:商业化数据
如果你有具体的数据结构(StatsBomb 格式)或想用于篮球/电竞场景,我可以把代码改成对应版本。