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

wen python案例 2

统计高球传中争顶成功率

业务背景

在足球比赛中,高球传中争顶成功率是衡量球队进攻效率的重要指标,反映:

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

  • 边路传中质量
  • 中锋抢点能力
  • 前场高空球控制力

示例场景:某球队本赛季30场比赛,共产生 150次高球传中,48次 被本方球员成功争顶 → 成功率 = 48/150 = 32%


数据结构设计

模拟一场比赛的事件数据(简化版):

import pandas as pd
import numpy as np
# 模拟一场比赛的传中事件数据
data = {
    'event_id': range(1, 21),
    'minute': [5, 12, 18, 25, 33, 40, 45, 52, 58, 63, 68, 72, 76, 80, 83, 86, 88, 89, 90, 92],
    'player': ['张三','李四','张三','王五','张三','李四','赵六','张三','王五','李四',
               '张三','赵六','张三','王五','李四','张三','赵六','张三','王五','李四'],
    'cross_type': ['高球','高球','低平球','高球','高球','高球','低平球','高球','高球','高球',
                   '高球','高球','低平球','高球','高球','高球','高球','高球','低平球','高球'],
    'target_player': ['前锋A','前锋A','前锋B','前锋A','前锋B','前锋A','前锋A','前锋A','前锋B','前锋A',
                      '前锋A','前锋B','前锋A','前锋A','前锋B','前锋A','前锋A','前锋B','前锋A','前锋A'],
    'duel_result': ['成功','成功','失败','失败','成功','失败','成功','成功','失败','成功',
                    '失败','成功','失败','成功','失败','成功','失败','成功','失败','成功'],
    'is_high_ball': [True,True,False,True,True,True,False,True,True,True,
                     True,True,False,True,True,True,True,True,False,True]
}
df = pd.DataFrame(data)
print(df)

核心统计函数

def calc_aerial_success_rate(df, cross_type='高球'):
    """
    统计高球传中争顶成功率
    :param df: 事件数据DataFrame
    :param cross_type: 传中类型(默认高球)
    :return: 统计结果字典
    """
    # 1. 筛选高球传中事件
    high_balls = df[df['cross_type'] == cross_type].copy()
    total = len(high_balls)
    success = (high_balls['duel_result'] == '成功').sum()
    failed = total - success
    rate = success / total * 100 if total > 0 else 0
    return {
        '高球传中总数': total,
        '争顶成功数': success,
        '争顶失败数': failed,
        '争顶成功率(%)': round(rate, 2)
    }
# 调用
result = calc_aerial_success_rate(df, '高球')
print("=" * 40)
print("📊 全场高球传中争顶统计")
print("=" * 40)
for k, v in result.items():
    print(f"{k}: {v}")

输出示例:

高球传中总数: 16
争顶成功数: 10
争顶失败数: 6
争顶成功率(%): 62.5

进阶分析:多维度统计

按球员统计(谁是传中王?)

# 按传球人统计
by_crosser = df[df['cross_type'] == '高球'].groupby('player').agg(
    传中次数=('event_id', 'count'),
    成功次数=('duel_result', lambda x: (x == '成功').sum())
).reset_index()
by_crosser['成功率(%)'] = (by_crosser['成功次数'] / by_crosser['传中次数'] * 100).round(1)
by_crosser = by_crosser.sort_values('成功率(%)', ascending=False)
print("\n👤 各球员高球传中成功率:")
print(by_crosser)

按接球人(前锋)统计

# 按争顶球员统计
by_target = df[df['cross_type'] == '高球'].groupby('target_player').agg(
    争顶次数=('event_id', 'count'),
    成功次数=('duel_result', lambda x: (x == '成功').sum())
).reset_index()
by_target['成功率(%)'] = (by_target['成功次数'] / by_target['争顶次数'] * 100).round(1)
print("\n🎯 各前锋争顶成功率:")
print(by_target)

按比赛阶段统计

# 按上下半场分析
def get_half(minute):
    return '上半场' if minute <= 45 else '下半场'
df['half'] = df['minute'].apply(get_half)
half_stats = df[df['cross_type'] == '高球'].groupby('half').agg(
    传中数=('event_id', 'count'),
    成功数=('duel_result', lambda x: (x == '成功').sum())
)
half_stats['成功率(%)'] = (half_stats['成功数'] / half_stats['传中数'] * 100).round(1)
print("\n⏱️ 上下半场高球传中对比:")
print(half_stats)

可视化输出

import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
fig, axes = plt.subplots(1, 3, figsize=(15, 4))
# 图1:整体成功率饼图
axes[0].pie([result['争顶成功数'], result['争顶失败数']],
            labels=['成功', '失败'], autopct='%1.1f%%',
            colors=['#2ecc71', '#e74c3c'])
axes[0].set_title(f"整体成功率 ({result['争顶成功率(%)']}%)")
# 图2:球员成功率柱状图
axes[1].bar(by_crosser['player'], by_crosser['成功率(%)'], color='#3498db')
axes[1].set_title('各球员传中成功率')
axes[1].set_ylabel('成功率 (%)')
axes[1].axhline(y=50, color='red', linestyle='--', alpha=0.5)
# 图3:按半场对比
axes[2].bar(half_stats.index, half_stats['成功率(%)'], color=['#9b59b6', '#f39c12'])
axes[2].set_title('上下半场成功率')
axes[2].set_ylabel('成功率 (%)')
plt.tight_layout()
plt.savefig('aerial_success.png', dpi=100)
plt.show()

扩展:读取真实比赛数据(StatsBomb 示例)

# 使用 statsbombpy 读取真实比赛数据
# pip install statsbombpy
from statsbombpy import sb
# 示例:曼城某场比赛
events = sb.events(match_id=3788741)  
def extract_aerial_crosses(events):
    """从StatsBomb数据中提取高球传中争顶事件"""
    crosses = events[
        (events['type'] == 'Pass') &
        (events['pass_height'] == 'High Pass') &
        (events['pass_cross'] == True)
    ].copy()
    total = len(crosses)
    # 匹配后的争顶结果
    success = crosses['pass_outcome'].isna().sum()  # 无outcome意味着找到队友
    return {
        '高球传中数': total,
        '成功率(%)': round(success / total * 100, 2) if total > 0 else 0
    }
# result = extract_aerial_crosses(events)
# print(result)

完整可运行代码(一键复制)

import pandas as pd
def full_report(df):
    """生成完整的高球传中争顶分析报告"""
    hb = df[df['cross_type'] == '高球']
    print("=" * 50)
    print("⚽ 高球传中争顶成功率分析报告")
    print("=" * 50)
    # 总览
    total = len(hb)
    success = (hb['duel_result'] == '成功').sum()
    print(f"\n【总体】")
    print(f"  高球传中总次数: {total}")
    print(f"  争顶成功次数:   {success}")
    print(f"  争顶成功率:     {success/total*100:.2f}%")
    # 球员维度
    print(f"\n【按传球球员】")
    stats = hb.groupby('player').agg(
        次数=('event_id','count'),
        成功=('duel_result', lambda x:(x=='成功').sum())
    )
    stats['成功率'] = (stats['成功']/stats['次数']*100).round(1).astype(str) + '%'
    print(stats.to_string())
    # 前锋维度
    print(f"\n【按争顶前锋】")
    stats2 = hb.groupby('target_player').agg(
        次数=('event_id','count'),
        成功=('duel_result', lambda x:(x=='成功').sum())
    )
    stats2['成功率'] = (stats2['成功']/stats2['次数']*100).round(1).astype(str) + '%'
    print(stats2.to_string())
full_report(df)

关键点总结

维度 说明
筛选条件 cross_type=='高球' 或 pass_height=='High Pass'
成功定义 传中被本方球员争顶到(duel_result=='成功')
核心公式 成功率 = 成功次数 / 总传中数 × 100%
分析维度 整体、球员、前锋、时间段、比赛场次

需要我针对具体数据源(如 Opta、Wyscout、StatsBomb 或 Excel 报表)做进一步适配,或加入落点区域热力图、对手防守球员对抗分析吗?

上一篇python案例对这次补射机会有何预判?

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

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

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