python案例统计高球传中争顶成功率?

wen python案例 8

高球传中争顶成功率统计案例

业务背景

在足球数据分析中,高球传中争顶成功率是衡量球队边路进攻质量和空中对抗能力的关键指标,通常定义为:

python案例统计高球传中争顶成功率?

  • 传中球:从边路或肋部向禁区方向的高球传递
  • 争顶成功:传中后进攻球员在禁区内赢得第一落点的头球
  • 成功率 = 争顶成功次数 / 有效高球传中次数 × 100%

下面用 Python 模拟一套完整的数据统计流程。


数据准备(模拟数据)

import pandas as pd
import numpy as np
np.random.seed(42)
# 模拟 200 次高球传中事件
n = 200
data = pd.DataFrame({
    "event_id": range(1, n + 1),
    "player": np.random.choice(["边锋A", "边锋B", "边后卫C", "边后卫D"], n),
    "minute": np.random.randint(1, 91, n),
    "cross_type": np.random.choice(["弧线球", "平高球", "外旋球"], n),
    "zone": np.random.choice(["前点", "中路", "后点"], n),
    # 争顶结果:1=成功,0=失败
    "aerial_won": np.random.choice([0, 1], n, p=[0.55, 0.45]),
    # 是否为有效传中(未出底线/未直接被门将没收)
    "valid_cross": np.random.choice([0, 1], n, p=[0.1, 0.9]),
})
print(data.head())

字段说明: | 字段 | 含义 | |------|------| | player | 传中球员 | | cross_type | 传中脚法 | | zone | 落点区域(前点/中路/后点) | | aerial_won | 是否争顶成功(1/0) | | valid_cross | 是否为有效高球传中(1/0) |


核心统计逻辑

# 只统计有效高球传中
valid = data[data["valid_cross"] == 1].copy()
# 总体争顶成功率
total_cross = len(valid)
total_won = valid["aerial_won"].sum()
overall_rate = total_won / total_cross * 100
print(f"有效高球传中: {total_cross} 次")
print(f"争顶成功: {total_won} 次")
print(f"总体争顶成功率: {overall_rate:.2f}%")

多维度分组统计

按球员统计

by_player = valid.groupby("player").agg(
    传中次数=("event_id", "count"),
    争顶成功=("aerial_won", "sum"),
).reset_index()
by_player["争顶成功率(%)"] = (
    by_player["争顶成功"] / by_player["传中次数"] * 100
).round(2)
by_player = by_player.sort_values("争顶成功率(%)", ascending=False)
print(by_player)

按落点区域统计

by_zone = valid.groupby("zone").agg(
    传中次数=("event_id", "count"),
    争顶成功=("aerial_won", "sum"),
)
by_zone["争顶成功率(%)"] = (by_zone["争顶成功"] / by_zone["传中次数"] * 100).round(2)
print(by_zone)

按传中脚法统计

by_type = valid.groupby("cross_type").agg(
    传中次数=("event_id", "count"),
    争顶成功=("aerial_won", "sum"),
)
by_type["争顶成功率(%)"] = (by_type["争顶成功"] / by_type["传中次数"] * 100).round(2)
print(by_type)

交叉透视表(球员 × 落点)

pivot = valid.pivot_table(
    index="player",
    columns="zone",
    values="aerial_won",
    aggfunc="mean"
) * 100
print(pivot.round(2))

进阶分析:置信区间与样本量提醒

样本小时,成功率波动大,可加入 威尔逊置信区间:

from math import sqrt
def wilson_ci(success, n, z=1.96):
    if n == 0:
        return (0, 0)
    p = success / n
    denom = 1 + z**2 / n
    center = (p + z**2 / (2*n)) / denom
    margin = z * sqrt(p*(1-p)/n + z**2/(4*n**2)) / denom
    return (round((center - margin)*100, 2), round((center + margin)*100, 2))
by_player[["下限(%)", "上限(%)"]] = by_player.apply(
    lambda r: pd.Series(wilson_ci(r["争顶成功"], r["传中次数"])),
    axis=1
)
print(by_player)

⚠️ 样本 <30 次的球员,成功率指标仅供参考。


可视化

import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# 球员成功率
axes[0].bar(by_player["player"], by_player["争顶成功率(%)"], color="steelblue")
axes[0].set_title("各球员高球传中争顶成功率")
axes[0].set_ylabel("成功率(%)")
axes[0].axhline(overall_rate, color="red", linestyle="--", label=f"总体 {overall_rate:.1f}%")
axes[0].legend()
# 区域成功率
axes[1].bar(by_zone.index, by_zone["争顶成功率(%)"], color="darkorange")
axes[1].set_title("不同落点区域争顶成功率")
axes[1].set_ylabel("成功率(%)")
plt.tight_layout()
plt.show()

输出示例(模拟结果)

有效高球传中: 178 次
争顶成功: 79 次
总体争顶成功率: 44.38%
     player  传中次数  争顶成功  争顶成功率(%)
   边锋B       42      23       54.76
   边后卫C     41      19       46.34
   边锋A       48      20       41.67
   边后卫D     47      17       36.17
  zone  传中次数  争顶成功  争顶成功率(%)
  后点    60      32       53.33
  前点    55      24       43.64
  中路    63      23       36.51

结论示例:

  • 边锋B的高球传中质量最高(成功率 54.8%),且样本充足
  • 后点落点争顶成功率显著高于中路——说明球队在防守后点传中时存在盯人漏洞
  • 中路传中虽次数多,但成功率最低,建议优化中路抢点跑位或调整传中弧线

扩展建议

若对接真实数据(如 Opta / StatsBomb / Wyscout),可替换为:

  1. StatsBomb 事件数据:筛选 pass.type == "Cross" 且 pass.height == "High Pass"
  2. 争顶事件关联:将传中事件与后续 Duel 事件(type=Aerial)通过 possession 或时间窗口关联
  3. xG 结合分析:传中 → 争顶 → 射门的转化链建模

需要我进一步演示 StatsBomb 真实数据接入或 传中→射门链路分析的代码,可以告诉我。

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

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