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

- 边路传中质量
- 中锋抢点能力
- 前场高空球控制力
示例场景:某球队本赛季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 报表)做进一步适配,或加入落点区域热力图、对手防守球员对抗分析吗?
版权声明: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直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播