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

场景说明
"交叉跑位"通常指两名进攻球员相互穿插换位(如边锋内切+边后卫套边、双前锋交叉换位),从而拉扯防线形成威胁,我们需要:
- 从事件数据中识别"交叉跑位"事件
- 判断该跑位是否形成了"威胁"(射门、关键传球、进入禁区等)
- 统计威胁次数
数据结构设计
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 / 自采坐标),我可以帮你改成直接从坐标计算"交叉跑位"(两人轨迹交汇)再统计威胁的版本,需要吗?
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播