界外球进攻威胁统计脚本
下面是一个用于统计足球比赛中界外球进攻威胁次数的实战脚本方案,先说明指标定义,再给出可落地的代码。

指标定义(关键)
"界外球进攻威胁"通常需要满足:界外球发出后 N 秒内(如 15 秒),球队完成一次威胁进攻,威胁进攻可定义为以下任一:
- 进入进攻三区(前场 1/3)
- 禁区内触球/射门
- 预期进球值(xG) ≥ 阈值
- 形成射门
不同数据源字段不同,下面用通用事件流思路实现。
脚本(Python + pandas)
假设你有事件数据 events.csv,字段包括:match_id, team, event_type, minute, second, x, y, xg(坐标归一化 0–100,x 为进攻方向)。
import pandas as pd
# ---------- 参数 ----------
WINDOW_SEC = 15 # 界外球后多少秒内的进攻算"关联"
ATTACK_THIRD_X = 66.7 # 进攻三区起点(x>66.7 为前场1/3)
BOX_X, BOX_Y = 83, 21 # 简化禁区判定
XG_THRESHOLD = 0.05 # 威胁射门xG阈值
def to_abs_sec(row):
return row["minute"] * 60 + row["second"]
def is_threat(ev):
"""判断单个事件是否为威胁性动作"""
if ev["event_type"] in ("shot", "shot_on_target"):
return ev.get("xg", 0) >= XG_THRESHOLD
if ev["event_type"] == "touch":
# 禁区内触球
return ev["x"] >= BOX_X and abs(ev["y"] - 50) <= BOX_Y
return ev["x"] >= ATTACK_THIRD_X # 进入进攻三区
def count_threat_after_throwins(df):
df = df.copy()
df["t"] = df.apply(to_abs_sec, axis=1)
results = []
for (mid, team), g in df.groupby(["match_id", "team"]):
g = g.sort_values("t").reset_index(drop=True)
throwins = g[g["event_type"] == "throw_in"]
for _, ti in throwins.iterrows():
t0 = ti["t"]
# 同一球队在窗口内的事件
window = g[(g["t"] > t0) & (g["t"] <= t0 + WINDOW_SEC)]
threat = window[window.apply(is_threat, axis=1)]
results.append({
"match_id": mid,
"team": team,
"throwin_time": f"{ti['minute']}:{ti['second']:02d}",
"threat_count": len(threat),
"is_threatening": int(len(threat) > 0),
})
return pd.DataFrame(results)
# ---------- 使用 ----------
events = pd.read_csv("events.csv")
detail = count_threat_after_throwins(events)
# 汇总:每队"有威胁的界外球次数"与占比
summary = detail.groupby(["match_id", "team"]).agg(
total_throwins=("throwin_time", "count"),
threatening_throwins=("is_threatening", "sum"),
).reset_index()
summary["threat_rate"] = summary["threatening_throwins"] / summary["total_throwins"]
print(summary)
summary.to_csv("throwin_threat_summary.csv", index=False)
输出示例
| match_id | team | total_throwins | threatening_throwins | threat_rate |
|---|---|---|---|---|
| 001 | A队 | 24 | 7 | 29 |
| 001 | B队 | 19 | 3 | 16 |
可扩展点
- 对手威胁:把
team换成"界外球后任意一方威胁",统计"被反击威胁"。 - 位置细分:按界外球发生位置(前场/中场/后场)分组统计威胁率。
- 链式进攻:要求窗口内事件属于同一进攻序列(用
possession_id字段过滤),避免把死球重启后的独立进攻算进来。 - 对手失球:窗口内若对方进球/射门,可记为"界外球导致的防守威胁"。
需要你确认的信息
为了给出更贴合的脚本,请告诉我:
- 数据来源是 Opta / StatsBomb / Wyscout / 自采?字段名不同,映射需调整。
- "威胁"的判定口径是否用 xG、射门、进攻三区 还是组合?
- 时间窗口用 15 秒 还是按联赛惯例(如 10s/20s)?
- 是否需要区分 前场界外球(通常威胁更高)单独统计?
告诉我这几点,我可以把脚本改成直接匹配你数据格式的版本。