实用脚本如何评估教练换人得分能力?

wen 实用脚本 7

本文目录导读:

实用脚本如何评估教练换人得分能力?

  1. 核心思路
  2. 数据需求
  3. 指标体系设计
  4. 脚本实现(Python伪代码)
  5. 进阶:换人决策的反事实评估
  6. 落地建议

核心思路

教练换人得分能力 = 换人后球队进攻/防守表现的变化,剔除比赛情境(比分、时间、对手强度)后的净效应。

关键要回答:

  1. 换人后进球/失球概率是否显著变化?
  2. 换人决策的时机是否合理?
  3. 换人选择(换谁上、换谁下)是否最优?

数据需求

数据类型 字段示例
比赛事件 进球、助攻、射门、传球、时间戳
换人记录 换人时间、下场球员、上场球员、当时比分
球员表现 上场前后xG/xA、跑动、对抗成功率
比赛情境 比分差、剩余时间、对手实力(Elo/排名)

指标体系设计

换人后净得分效应(核心指标)

NetGoalEffect = Σ(换人后球队进球) - Σ(换人后球队失球)
                按换人后在场时间归一化

更精细版本:用xG替代实际进球,减少样本噪声。

换人时机质量

TimingScore = 换人时球队xG差变化率 / 剩余时间

衡量是否在球队势头下滑时及时调整。

换人选择价值

SubValue = 上场球员下场后xG贡献 - 下场球员若留场的预期xG贡献

用球员个人xG/xA模型估算。

情境调整后的换人得分

用回归模型控制比分差、时间、对手强度:

ΔxG_per_min ~ β0 + β1·is_sub + β2·score_diff + β3·time + β4·opp_strength + ε

β1 即教练换人的净效应。


脚本实现(Python伪代码)

import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
import statsmodels.api as sm
# ---------- 1. 数据加载 ----------
subs = pd.read_csv("substitutions.csv")   # match_id, minute, player_off, player_on, score_diff
events = pd.read_csv("events.csv")        # match_id, minute, type, team, xG
# ---------- 2. 构建换人前后窗口 ----------
WINDOW = 15  # 换人前后各15分钟
def window_xg(match_events, team, start, end):
    mask = (match_events.team == team) & \
           (match_events.minute >= start) & (match_events.minute < end)
    return match_events.loc[mask, "xG"].sum()
records = []
for _, s in subs.iterrows():
    ev = events[events.match_id == s.match_id]
    pre  = window_xg(ev, s.team, s.minute - WINDOW, s.minute)
    post = window_xg(ev, s.team, s.minute, s.minute + WINDOW)
    records.append({
        "match_id": s.match_id,
        "coach": s.coach,
        "minute": s.minute,
        "score_diff": s.score_diff,
        "pre_xg": pre,
        "post_xg": post,
        "delta_xg": post - pre,
    })
df = pd.DataFrame(records)
# ---------- 3. 情境调整回归 ----------
X = sm.add_constant(df[["score_diff", "minute"]])
y = df["delta_xg"]
model = sm.OLS(y, X).fit()
df["adjusted_delta"] = model.resid + model.params["const"]  # 剔除情境后的净效应
# ---------- 4. 教练层面聚合 ----------
coach_score = df.groupby("coach").agg(
    n_subs=("adjusted_delta", "count"),
    mean_delta=("adjusted_delta", "mean"),
    std_delta=("adjusted_delta", "std"),
).reset_index()
# 收缩估计(小样本教练向均值收缩)
global_mean = df["adjusted_delta"].mean()
k = 10  # 收缩强度
coach_score["shrunk_score"] = (
    (coach_score.n_subs * coach_score.mean_delta + k * global_mean)
    / (coach_score.n_subs + k)
)
coach_score = coach_score.sort_values("shrunk_score", ascending=False)
print(coach_score.head(20))

进阶:换人决策的反事实评估

若要评估“这次换人是否比不换更好”,可用:

  1. 匹配法:找相似情境(比分、时间、对手)下未换人的比赛片段作为对照。
  2. 因果推断:用倾向得分匹配(PSM)或双重差分(DID)估计换人的因果效应。
  3. 球员级模型:用个人xG模型估算“若A留场 vs B上场”的期望xG差。
# 倾向得分匹配示例
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import NearestNeighbors
# 特征:比分差、时间、控球率、射门差
features = ["score_diff", "minute", "possession_diff", "shots_diff"]
ps_model = LogisticRegression().fit(df[features], df["is_sub"])
df["ps"] = ps_model.predict_proba(df[features])[:, 1]
# 对每个换人样本,在未换人样本中找最近邻
# 计算 ATT = E[Y|sub] - E[Y|no_sub, matched]

落地建议

步骤 工具 产出
数据管道 Python + SQL 换人事件表 + 事件流
指标计算 pandas / statsmodels 教练换人得分排名
可视化 matplotlib / Tableau 换人时机热图、净效应分布
验证 分赛季交叉验证 稳定性检验

注意事项:

  • 样本量小:单教练单赛季换人次数有限,需多赛季聚合或贝叶斯收缩。
  • 混杂因素:比分落后时换人本身更激进,必须做情境调整。
  • xG优于实际进球:减少随机性,提高信度。
  • 区分换人类型:战术换人 vs 伤病换人 vs 时间消耗换人,应分开评估。

如果需要,我可以进一步给出某个具体环节的完整代码(比如PSM匹配、贝叶斯层级模型、或可视化看板)。

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

友情链接攻略窝 · 礼包窝 · 配置窝 · 换算窝 · 算法窝 · 查文窝 · 手册窝 · 问答窝 · 全文搜 · 手册库
相关站点礼包窝 · 查文窝