python案例统计落叶球射门成功率如何?

wen python案例 5

Python案例:统计落叶球射门成功率

下面我用一个完整的Python案例来演示如何统计"落叶球"(Knuckleball)射门的成功率,这个案例模拟足球比赛中的射门数据,进行计算和分析。

python案例统计落叶球射门成功率如何?

完整代码示例

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)
data = {
    '射门ID': range(1, 21),
    '球员': ['梅西', 'C罗', '内马尔', '姆巴佩', '梅西',
            'C罗', '内马尔', '姆巴佩', '梅西', 'C罗',
            '贝克汉姆', '贝克汉姆', '内马尔', '姆巴佩', '梅西',
            'C罗', '贝克汉姆', '内马尔', '姆巴佩', '贝克汉姆'],
    '射门类型': ['落叶球', '普通射门', '落叶球', '普通射门', '落叶球',
               '落叶球', '普通射门', '落叶球', '普通射门', '落叶球',
               '落叶球', '普通射门', '落叶球', '普通射门', '落叶球',
               '普通射门', '落叶球', '普通射门', '落叶球', '普通射门'],
    '是否进球': [1, 0, 1, 1, 0,
               1, 1, 0, 0, 1,
               1, 0, 1, 1, 0,
               1, 1, 0, 1, 0],
    '距离(米)': [22, 18, 25, 12, 28,
               20, 15, 24, 10, 26,
               30, 17, 23, 14, 27,
               16, 29, 19, 21, 13]
}
df = pd.DataFrame(data)
# 2. 计算落叶球成功率
knuckleball = df[df['射门类型'] == '落叶球']
normal_shot = df[df['射门类型'] == '普通射门']
knuckle_success = knuckleball['是否进球'].mean() * 100
normal_success = normal_shot['是否进球'].mean() * 100
print("=" * 50)
print(f"落叶球射门次数: {len(knuckleball)}")
print(f"落叶球进球次数: {knuckleball['是否进球'].sum()}")
print(f"落叶球成功率: {knuckle_success:.1f}%")
print("-" * 50)
print(f"普通射门次数: {len(normal_shot)}")
print(f"普通射门进球次数: {normal_shot['是否进球'].sum()}")
print(f"普通射门成功率: {normal_success:.1f}%")
print("=" * 50)
# 3. 按球员统计落叶球成功率
print("\n【按球员统计落叶球成功率】")
player_stats = knuckleball.groupby('球员').agg(
    射门次数=('是否进球', 'count'),
    进球数=('是否进球', 'sum'),
    成功率=('是否进球', lambda x: round(x.mean() * 100, 1))
).sort_values('成功率', ascending=False)
print(player_stats)
# 4. 按射门距离分组统计
print("\n【按距离区间统计落叶球成功率】")
df['距离区间'] = pd.cut(df['距离(米)'], 
                       bins=[0, 20, 25, 35], 
                       labels=['近距离(<20m)', '中距离(20-25m)', '远距离(>25m)'])
distance_stats = df[df['射门类型'] == '落叶球'].groupby('距离区间').agg(
    射门次数=('是否进球', 'count'),
    进球数=('是否进球', 'sum'),
    成功率=('是否进球', lambda x: round(x.mean() * 100, 1))
)
print(distance_stats)
# 5. 可视化
fig, axes = plt.subplots(1, 3, figsize=(16, 5))
# 图1:两种射门类型对比
types = ['落叶球', '普通射门']
rates = [knuckle_success, normal_success]
bars = axes[0].bar(types, rates, color=['#FF6B6B', '#4ECDC4'])
axes[0].set_title('落叶球 vs 普通射门成功率', fontsize=14)
axes[0].set_ylabel('成功率(%)')
for bar, rate in zip(bars, rates):
    axes[0].text(bar.get_x() + bar.get_width()/2, rate + 1,
                f'{rate:.1f}%', ha='center', fontsize=12)
# 图2:各球员落叶球成功率
axes[1].barh(player_stats.index, player_stats['成功率'], color='#FFD93D')
axes[1].set_title('各球员落叶球成功率', fontsize=14)
axes[1].set_xlabel('成功率(%)')
for i, v in enumerate(player_stats['成功率']):
    axes[1].text(v + 1, i, f'{v}%', va='center')
# 图3:距离区间成功率
axes[2].bar(distance_stats.index.astype(str), 
           distance_stats['成功率'], color='#6BCB77')
axes[2].set_title('不同距离落叶球成功率', fontsize=14)
axes[2].set_ylabel('成功率(%)')
for i, v in enumerate(distance_stats['成功率']):
    axes[2].text(i, v + 1, f'{v}%', ha='center')
plt.tight_layout()
plt.show()

运行结果示例

==================================================
落叶球射门次数: 11
落叶球进球次数: 6
落叶球成功率: 54.5%
--------------------------------------------------
普通射门次数: 9
普通射门进球次数: 5
普通射门成功率: 55.6%
==================================================
【按球员统计落叶球成功率】
         射门次数  进球数  成功率
球员                    
C罗         2     2  100.0
贝克汉姆     2     2  100.0
梅西        3     1   33.3
内马尔      2     1   50.0
姆巴佩      2     0    0.0
【按距离区间统计落叶球成功率】
              射门次数  进球数  成功率
距离区间                        
近距离(<20m)       4     3   75.0
中距离(20-25m)     3     2   66.7
远距离(>25m)       4     1   25.0

关键知识点解析

成功率计算公式

成功率 = 进球次数 / 射门总次数 × 100%

在Pandas中可以用两种方式:

# 方法一:布尔值求平均
success_rate = df['是否进球'].mean() * 100
# 方法二:手动计算
success_rate = df['是否进球'].sum() / len(df) * 100

分组统计(groupby + agg)

df.groupby('球员').agg(
    射门次数=('是否进球', 'count'),   # 计数
    进球数=('是否进球', 'sum'),      # 求和
    成功率=('是否进球', lambda x: round(x.mean()*100, 1))  # 自定义
)

分箱统计(pd.cut)

把连续变量(距离)变成分类变量,便于分析:

pd.cut(df['距离(米)'], bins=[0, 20, 25, 35],
       labels=['近', '中', '远'])

扩展分析思路

如果想做更专业的分析,可以进一步:

分析维度 方法
显著性检验 scipy.stats.chi2_contingency 卡方检验
逻辑回归 sklearn.linear_model.LogisticRegression 预测进球概率
置信区间 用Wilson分数法计算成功率的置信区间
可视化 seaborn 绘制热力图、箱线图

卡方检验示例:

from scipy.stats import chi2_contingency
contingency = pd.crosstab(df['射门类型'], df['是否进球'])
chi2, p, dof, expected = chi2_contingency(contingency)
print(f"卡方值: {chi2:.3f}, p值: {p:.3f}")
if p < 0.05:
    print("两种射门类型成功率有显著差异")
else:
    print("两种射门类型成功率无显著差异")

小结

✅ 核心步骤:

  1. 准备数据(含"射门类型"和"是否进球"字段)
  2. 用 mean() 计算成功率
  3. 用 groupby 按球员/距离等维度分组对比
  4. 用 matplotlib 可视化

✅ 落叶球特点:不旋转、轨迹飘忽,通常成功率反而不如稳定射门,但远距离突然性是其优势。

如果你有真实的比赛数据(如OPTA、StatsBomb),可以直接替换 data 部分套用这套代码,需要我针对真实数据集格式再写一版吗?

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