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

wen python案例 1

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

下面是一个完整的 Python 案例,模拟统计足球比赛中高球传中争顶成功率,包含数据建模、统计计算和可视化。

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

场景说明

高球传中争顶成功率 = 争顶成功次数 / 总争顶次数 × 100%

通常按球员、球队、区域等维度统计,下面用模拟数据演示完整流程。

完整代码

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# ---------- 1. 构造模拟数据 ----------
np.random.seed(42)
players = ['张伟', '李强', '王磊', '刘洋', '陈晨', '赵鹏', '孙浩', '周杰']
teams   = ['A队', 'B队']
data = []
for i in range(200):  # 200次传中事件
    player = np.random.choice(players)
    team   = 'A队' if player in players[:4] else 'B队'
    zone   = np.random.choice(['禁区中路', '禁区肋部', '禁区外围'])
    # 模拟争顶结果:中路成功率高一些
    base = {'禁区中路': 0.55, '禁区肋部': 0.45, '禁区外围': 0.35}[zone]
    success = np.random.rand() < base
    data.append([i+1, team, player, zone, int(success)])
df = pd.DataFrame(data, columns=['事件ID', '球队', '球员', '区域', '争顶成功'])
print(df.head())
# ---------- 2. 球员维度统计 ----------
def stat_success(group):
    total = len(group)
    wins  = group['争顶成功'].sum()
    rate  = wins / total * 100
    return pd.Series({'争顶次数': total, '成功次数': wins, '成功率(%)': round(rate, 2)})
player_stat = df.groupby('球员').apply(stat_success).sort_values('成功率(%)', ascending=False)
print("\n=== 球员争顶成功率 ===")
print(player_stat)
# ---------- 3. 球队维度统计 ----------
team_stat = df.groupby('球队').apply(stat_success)
print("\n=== 球队争顶成功率 ===")
print(team_stat)
# ---------- 4. 区域维度统计 ----------
zone_stat = df.groupby('区域').apply(stat_success).sort_values('成功率(%)', ascending=False)
print("\n=== 区域争顶成功率 ===")
print(zone_stat)
# ---------- 5. 球队+区域交叉统计 ----------
cross = df.groupby(['球队', '区域'])['争顶成功'].agg(['count', 'sum'])
cross['成功率(%)'] = (cross['sum'] / cross['count'] * 100).round(2)
print("\n=== 球队×区域交叉统计 ===")
print(cross)
# ---------- 6. 可视化 ----------
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 球员成功率
player_stat['成功率(%)'].sort_values().plot(kind='barh', ax=axes[0], color='steelblue')
axes[0].set_title('各球员高球争顶成功率')
axes[0].set_xlabel('成功率(%)')
# 区域成功率
zone_stat['成功率(%)'].plot(kind='bar', ax=axes[1], color='coral')
axes[1].set_title('各区域高球争顶成功率')
axes[1].set_ylabel('成功率(%)')
for i, v in enumerate(zone_stat['成功率(%)']):
    axes[1].text(i, v + 1, f'{v}%', ha='center')
plt.tight_layout()
plt.show()

预期输出示例

=== 球员争顶成功率 ===
     争顶次数  成功次数  成功率(%)
球员
陈晨      22     14     63.64
张伟      27     15     55.56
王磊      25     13     52.00
...

关键点扩展

① 成功率置信区间(Wilson 方法)

小样本时单纯比例不可靠,可用 Wilson 区间估计:

from statsmodels.stats.proportion import proportion_confint
def wilson(row, alpha=0.05):
    low, high = proportion_confint(row['成功次数'], row['争顶次数'], 
                                   method='wilson', alpha=alpha)
    return pd.Series({'下限(%)': round(low*100, 1), 
                      '上限(%)': round(high*100, 1)})
player_stat = player_stat.join(player_stat.apply(wilson, axis=1))
print(player_stat.sort_values('成功率(%)', ascending=False))

② 加权统计(考虑区域难度)

不同区域难度不同,可用加权成功率:

# 假设每区域权重(难度越高权重越小)
weights = {'禁区中路': 1.0, '禁区肋部': 0.9, '禁区外围': 0.7}
def weighted_rate(g):
    g = g.copy()
    g['权重'] = g['区域'].map(weights)
    return (g['争顶成功'] * g['权重']).sum() / g['权重'].sum() * 100
weighted = df.groupby('球员').apply(weighted_rate).round(2)
print("\n=== 加权成功率(%) ===")
print(weighted.sort_values(ascending=False))

③ 从真实数据导入

如果有 Opta / WyScout / StatsBomb 等数据:

# 例如从 StatsBomb 事件数据提取
# events = pd.read_json('events.json')
# 筛选 pass 类型为高球传中,且后续有 aerial_duel 事件

业务解读建议

指标 意义
整体成功率 球队传中战术执行效果
区域成功率 防守暴露的薄弱区域
球员成功率(含置信区间) 避免小样本误判
加权成功率 更公平地比较不同位置球员

如果需要 真实比赛数据接口(如免费公开的 StatsBomb 数据)、更复杂的 xG 关联分析,或按时间段/比赛分段统计,可以告诉我,我再补充。

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

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