综合python案例,边路传中成功率对比?

wen python案例 13

边路传中成功率对比分析

下面是一个完整的Python案例,对比不同边路(左路、右路)以及不同球员/球队的传中成功率。

综合python案例,边路传中成功率对比?

数据模拟与准备

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
np.random.seed(42)
# 模拟一场赛事/赛季的传中数据
teams = ['曼城', '利物浦', '阿森纳', '切尔西']
sides = ['左路', '右路']
data = []
for team in teams:
    for side in sides:
        # 每队每边路模拟 40-60 次传中
        n_crosses = np.random.randint(40, 60)
        # 不同球队/边路的成功率基准
        base_rate = np.random.uniform(0.20, 0.38)
        for _ in range(n_crosses):
            success = np.random.rand() < base_rate
            data.append({
                '球队': team,
                '边路': side,
                '成功': int(success),
                '传中类型': np.random.choice(['弧线球', '低平球', '倒三角']),
            })
df = pd.DataFrame(data)
print(df.head())
print(f"\n总传中次数: {len(df)}")

整体成功率统计

# 总体传中成功率
overall_rate = df['成功'].mean()
print(f"总体传中成功率: {overall_rate:.2%}")
# 按边路统计
side_stats = df.groupby('边路').agg(
    传中次数=('成功', 'count'),
    成功次数=('成功', 'sum'),
    成功率=('成功', 'mean')
).round(4)
side_stats['成功率'] = side_stats['成功率'].apply(lambda x: f"{x:.2%}")
print("\n按边路统计:")
print(side_stats)

输出示例:

总体传中成功率: 29.13%
按边路统计:
     传中次数  成功次数    成功率
边路                      
右路    191     59  30.89%
左路    203     53  26.11%

按球队 × 边路对比

# 球队-边路交叉统计
cross_stats = df.groupby(['球队', '边路'])['成功'].agg(['count', 'sum', 'mean'])
cross_stats.columns = ['传中次数', '成功次数', '成功率']
cross_stats['成功率'] = cross_stats['成功率'].round(3)
print(cross_stats)
# 透视表,便于对比
pivot = df.pivot_table(index='球队', columns='边路', values='成功', aggfunc='mean')
pivot = pivot.round(3)
print("\n各队左右路传中成功率对比:")
print(pivot)

可视化对比

fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 图1: 各队左右路传中成功率分组柱状图
pivot.plot(kind='bar', ax=axes[0], color=['#4C72B0', '#DD8452'], width=0.75)
axes[0].set_title('各队左路 vs 右路传中成功率', fontsize=13)
axes[0].set_ylabel('成功率')
axes[0].set_xticklabels(pivot.index, rotation=0)
axes[0].legend(title='边路')
axes[0].grid(axis='y', alpha=0.3)
# 图2: 整体边路成功率对比
side_mean = df.groupby('边路')['成功'].mean()
bars = axes[1].bar(side_mean.index, side_mean.values,
                   color=['#55A868', '#C44E52'], width=0.5)
axes[1].set_title('整体左右路传中成功率对比', fontsize=13)
axes[1].set_ylabel('成功率')
axes[1].set_ylim(0, 0.5)
for bar, v in zip(bars, side_mean.values):
    axes[1].text(bar.get_x() + bar.get_width()/2, v + 0.01,
                 f'{v:.1%}', ha='center', fontsize=12)
plt.tight_layout()
plt.show()

传中类型 × 边路 热力图

# 边路 × 传中类型 成功率热力图
heat = df.pivot_table(index='边路', columns='传中类型',
                      values='成功', aggfunc='mean')
plt.figure(figsize=(8, 4))
sns.heatmap(heat, annot=True, fmt='.1%', cmap='YlOrRd',
            cbar_kws={'label': '成功率'})'边路 × 传中类型 成功率热力图', fontsize=13)
plt.ylabel('')
plt.tight_layout()
plt.show()
print(heat.round(3))

核心结论输出

def report(df):
    print("=" * 50)
    print("        边路传中成功率对比报告")
    print("=" * 50)
    for side in ['左路', '右路']:
        sub = df[df['边路'] == side]
        rate = sub['成功'].mean()
        print(f"{side}: {len(sub)} 次传中, 成功率 {rate:.2%}")
    left = df[df['边路'] == '左路']['成功'].mean()
    right = df[df['边路'] == '右路']['成功'].mean()
    diff = right - left
    better = '右路' if diff > 0 else '左路'
    print(f"\n→ {better}传中成功率高出 {abs(diff):.2%}")
    # 寻找最佳组合
    best = df.groupby(['球队', '边路'])['成功'].mean().idxmax()
    best_rate = df.groupby(['球队', '边路'])['成功'].mean().max()
    print(f"→ 最高成功率组合: {best[0]} - {best[1]} ({best_rate:.2%})")
    print("=" * 50)
report(df)

输出示例:

==================================================
        边路传中成功率对比报告
==================================================
左路: 203 次传中, 成功率 26.11%
右路: 191 次传中, 成功率 30.89%
→ 右路传中成功率高出 4.78%
→ 最高成功率组合: 曼城 - 右路 (35.42%)
==================================================

进阶:统计显著性检验

from scipy.stats import chi2_contingency
# 构建列联表检验左右路成功率是否有显著差异
contingency = pd.crosstab(df['边路'], df['成功'])
print(contingency)
chi2, p, dof, expected = chi2_contingency(contingency)
print(f"\n卡方值: {chi2:.4f}, p值: {p:.4f}")
if p < 0.05:
    print("→ 左右路传中成功率存在统计学显著差异")
else:
    print("→ 左右路传中成功率差异不显著(可能为随机波动)")

扩展建议(真实数据接入)

  • 数据来源:可用 mplsoccer + StatsBomb 开源数据,或 Understat/FBref 爬取
  • 成功率定义:通常定义为「传中后队友首次触球成功」或「形成射门」
  • 进阶指标:xT(预期威胁)、xA(预期助攻)、传中落点热图
  • 场地分区:可进一步划分为边路 1/2/3 区对比
# 真实数据示例(StatsBomb)
# from mplsoccer import Sbopen
# parser = Sbopen()
# df_events, _, _, _ = parser.event(match_id=xxxx)
# crosses = df_events[df_events['type_name'] == 'Pass']
# crosses = crosses[crosses['pass_cross'] == True]

关键结论:通过该案例可对比左右路、各队、各传中类型的成功率差异,并可通过卡方检验验证差异是否显著,从而为球队战术布置(如何侧重某侧边路进攻)提供数据依据。

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