Python 案例分析:点球命中率对比
下面用 Python 构建一个完整的点球命中率对比分析案例,涵盖数据模拟、可视化与统计检验。

案例背景
对比不同球队/球员/情境下的点球命中率,
- 不同球队的点球命中率
- 主罚球员之间的对比
- 常规时间 vs 点球大战
- 不同联赛/赛事对比
代码实现
数据模拟
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
np.random.seed(42)
# 模拟5支球队的点球数据(射门数、命中数)
teams = ['球队A', '球队B', '球队C', '球队D', '球队E']
attempts = [120, 95, 150, 80, 110] # 总点球数
true_rates = [0.78, 0.72, 0.85, 0.68, 0.80] # 真实命中率
goals = [np.random.binomial(n, p) for n, p in zip(attempts, true_rates)]
df = pd.DataFrame({
'球队': teams,
'点球数': attempts,
'命中数': goals,
})
df['命中率'] = df['命中数'] / df['点球数']
df['命中率%'] = (df['命中率'] * 100).round(1)
print(df)
输出示例:
| 球队 | 点球数 | 命中数 | 命中率% |
|---|---|---|---|
| 球队A | 120 | 93 | 5 |
| 球队B | 95 | 68 | 6 |
| 球队C | 150 | 128 | 3 |
| 球队D | 80 | 54 | 5 |
| 球队E | 110 | 88 | 0 |
可视化对比
plt.figure(figsize=(10, 6))
sns.barplot(data=df, x='球队', y='命中率%', palette='viridis')
plt.axhline(df['命中率%'].mean(), color='red', linestyle='--', label=f'平均 {df["命中率%"].mean():.1f}%')'各球队点球命中率对比')
plt.ylabel('命中率 (%)')
plt.legend()
plt.tight_layout()
plt.show()
置信区间(Wilson 方法更稳健)
def wilson_ci(k, n, z=1.96):
p = k / n
denom = 1 + z**2 / n
center = (p + z**2 / (2*n)) / denom
margin = z * np.sqrt(p*(1-p)/n + z**2/(4*n**2)) / denom
return center - margin, center + margin
df[['CI_low', 'CI_high']] = df.apply(
lambda r: pd.Series(wilson_ci(r['命中数'], r['点球数'])), axis=1
)
df['CI'] = df.apply(lambda r: f"[{r.CI_low*100:.1f}%, {r.CI_high*100:.1f}%]", axis=1)
print(df[['球队', '命中率%', 'CI']])
卡方检验:各队命中率是否有显著差异
contingency = np.array([goals, np.array(attempts) - np.array(goals)]).T
chi2, p, dof, _ = stats.chi2_contingency(contingency)
print(f"卡方值={chi2:.2f}, p值={p:.4f}")
if p < 0.05:
print("各队点球命中率存在显著差异")
else:
print("各队点球命中率无显著差异")
两两对比(Fisher 精确检验 / 卡方)
from itertools import combinations
results = []
for (i, a), (j, b) in combinations(df.iterrows(), 2):
table = [[a['命中数'], a['点球数']-a['命中数']],
[b['命中数'], b['点球数']-b['命中数']]]
_, p = stats.fisher_exact(table)
results.append((a['球队'], b['球队'], p))
pairs = pd.DataFrame(results, columns=['队1', '队2', 'p值'])
pairs['显著差异'] = pairs['p值'] < 0.05
print(pairs.sort_values('p值'))
贝叶斯视角(Beta 后验分布)
from scipy.stats import beta
x = np.linspace(0.5, 1.0, 500)
plt.figure(figsize=(10, 5))
for _, r in df.iterrows():
a_post = r['命中数'] + 1 # 均匀先验 Beta(1,1)
b_post = r['点球数'] - r['命中数'] + 1
plt.plot(x, beta.pdf(x, a_post, b_post), label=r['球队'])'点球命中率的后验分布(Beta-Binomial 模型)')
plt.xlabel('命中率')
plt.ylabel('概率密度')
plt.legend()
plt.tight_layout()
plt.show()
典型结论示例
| 对比维度 | 结果 |
|---|---|
| 球队C vs 球队D | 3% vs 67.5%,差异显著(p<0.05) |
| 整体平均 | 约 77% |
| 最高/最低差 | 队C 领先队D 近 18 个百分点 |
| 卡方检验 | p<0.05,各队命中率差异具有统计学意义 |
真实数据中常见的规律(供参考)
若将本框架应用于真实赛事数据(如英超、世界杯),典型发现:
- 联赛差异:不同联赛点球命中率普遍在 75%–80% 区间,差异不大。
- 球员差异:顶级射手命中率可达 85%+,普通球员约 70%。
- 压力情境:点球大战命中率通常略低于常规时间(约降 3–5 个百分点)。
- 主罚顺序:先罚球队胜率略高(约 55–60%),但差异常不显著。
- 守门员影响:面对顶级门将,命中率可下降 5–10%。
分析要点提醒
- 样本量小:单一球员/短赛程数据波动大,必须给置信区间,不能只看命中率数字。
- 辛普森悖论:总体命中率差异可能被"点球难度"等混杂因素掩盖。
- 统计显著性 vs 实际意义:5 个百分点差异往往统计不显著,但对比赛结果影响巨大。
- 建议:结合 Wilson 置信区间 + 卡方检验 + 贝叶斯后验分布,多角度判断。
如果你有具体的真实数据集(如某联赛逐场点球记录 CSV),我可以帮你直接跑出上述对比图表和检验结果,需要我调整对比维度(如按赛季、主客场、球员)吗?
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播