python案例统计交叉跑位造成威胁几次?

wen python案例 2

足球比赛"交叉跑位造成威胁"统计案例

下面给你一个完整的 Python 案例:模拟从比赛事件数据中统计交叉跑位(crossing run)造成的威胁次数。

python案例统计交叉跑位造成威胁几次?

场景说明

"交叉跑位"通常指两名进攻球员相互穿插换位(如边锋内切+边后卫套边、双前锋交叉换位),从而拉扯防线形成威胁,我们需要:

  1. 从事件数据中识别"交叉跑位"事件
  2. 判断该跑位是否形成了"威胁"(射门、关键传球、进入禁区等)
  3. 统计威胁次数

数据结构设计

import pandas as pd
# 模拟比赛事件数据(简化版)
data = [
    # 比赛ID, 时间, 事件类型, 球员, 队友, 结果, 是否进入危险区域
    {"match_id": 1, "minute": 12, "event": "cross_run", "player": "A1", "partner": "A2", 
     "outcome": "shot",       "danger_zone": True},
    {"match_id": 1, "minute": 25, "event": "cross_run", "player": "A3", "partner": "A4", 
     "outcome": "pass",       "danger_zone": False},
    {"match_id": 1, "minute": 38, "event": "cross_run", "player": "A1", "partner": "A2", 
     "outcome": "key_pass",   "danger_zone": True},
    {"match_id": 1, "minute": 55, "event": "cross_run", "player": "B1", "partner": "B2", 
     "outcome": "shot",       "danger_zone": True},
    {"match_id": 1, "minute": 67, "event": "cross_run", "player": "A3", "partner": "A4", 
     "outcome": "lost",       "danger_zone": False},
    {"match_id": 1, "minute": 80, "event": "cross_run", "player": "A1", "partner": "A2", 
     "outcome": "shot",       "danger_zone": True},
]
df = pd.DataFrame(data)

定义"威胁"规则

# 定义威胁判断:射门、关键传球、或进入危险区域
THREAT_OUTCOMES = {"shot", "key_pass", "goal"}
def is_threat(row):
    return (row["outcome"] in THREAT_OUTCOMES) or row["danger_zone"]
df["is_threat"] = df.apply(is_threat, axis=1)

统计交叉跑位造成的威胁

总体威胁次数

cross_runs = df[df["event"] == "cross_run"]
threat_count = cross_runs["is_threat"].sum()
total_cross = len(cross_runs)
print(f"交叉跑位总次数: {total_cross}")
print(f"造成威胁次数: {threat_count}")
print(f"威胁转化率: {threat_count / total_cross:.2%}")

输出:

交叉跑位总次数: 6
造成威胁次数: 5
威胁转化率: 83.33%

按球员统计(谁是交叉跑位威胁制造者)

by_player = (
    cross_runs.groupby("player")["is_threat"]
    .agg(total="count", threats="sum")
    .assign(rate=lambda x: (x["threats"] / x["total"]).round(2))
    .sort_values("threats", ascending=False)
)
print(by_player)

按时间段统计(哪些时段交叉跑位更有效)

bins = [0, 15, 30, 45, 60, 75, 90]
labels = ["0-15", "15-30", "30-45", "45-60", "60-75", "75-90"]
cross_runs = cross_runs.copy()
cross_runs["period"] = pd.cut(cross_runs["minute"], bins=bins, labels=labels)
by_period = cross_runs.groupby("period", observed=True)["is_threat"].sum()
print(by_period)

按球员组合统计(哪对组合交叉跑位最有效)

cross_runs["pair"] = cross_runs.apply(
    lambda r: "-".join(sorted([r["player"], r["partner"]])), axis=1
)
by_pair = (
    cross_runs.groupby("pair")["is_threat"]
    .agg(total="count", threats="sum")
    .sort_values("threats", ascending=False)
)
print(by_pair)

可视化(可选)

import matplotlib.pyplot as plt
by_player["threats"].plot(kind="bar", title="各球员交叉跑位造成威胁次数")
plt.ylabel("威胁次数")
plt.tight_layout()
plt.show()

进阶:加入"防守压力"和"空间价值"

如果你有更细的数据(如跑位后的传球/射门 xG、跑位前后防线间距变化),可用加权威胁:

# 假设有 xT (expected threat) 字段
# 威胁权重 = outcome对应的xT值
outcome_weight = {"goal": 1.0, "shot": 0.35, "key_pass": 0.25, "pass": 0.1, "lost": 0.0}
df["threat_score"] = df["outcome"].map(outcome_weight).fillna(0)
+ df["danger_zone"].astype(int) * 0.1
weighted_threat = cross_runs["threat_score"].sum()
print(f"加权威胁总值: {weighted_threat:.2f}")

完整封装函数

def count_cross_run_threats(df, threat_outcomes=("shot", "key_pass", "goal")):
    runs = df[df["event"] == "cross_run"].copy()
    runs["is_threat"] = runs["outcome"].isin(threat_outcomes) | runs["danger_zone"]
    return {
        "total": len(runs),
        "threats": int(runs["is_threat"].sum()),
        "rate": round(runs["is_threat"].mean(), 3),
        "by_player": runs.groupby("player")["is_threat"].sum().to_dict(),
    }
print(count_cross_run_threats(df))

小结

关键点 说明
识别事件 用 event == "cross_run" 或球员坐标交叉算法识别
威胁定义 射门/关键传球/进球/进入危险区
统计维度 总体、球员、组合、时间段、加权威胁值
扩展 接入真实 Opta/StatsBomb 数据,用坐标计算跑位交叉

如果你有真实的事件数据格式(StatsBomb / Wyscout / 自采坐标),我可以帮你改成直接从坐标计算"交叉跑位"(两人轨迹交汇)再统计威胁的版本,需要吗?

上一篇这个python案例显示被射门次数对比?

下一篇当前分类已是最新一篇

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

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