综合赛后 Python 案例:两队实力真实差距分析
这是一个经典的体育数据分析问题,单场比赛的结果往往包含大量随机性(运气、裁判、状态波动),要评估两队真实实力差距,需要综合多场比赛数据。

核心思路
真实实力差距 ≠ 单场比分差
需要从多个维度综合估计:
| 维度 | 说明 |
|---|---|
| 期望进球 (xG) | 剔除运气成分的进攻质量 |
| 历史交锋 | 多场平均而非单场 |
| 控球/射门/射正 | 场面压制程度 |
| 近期状态 | 加权近期比赛 |
| 主客场因素 | 分离主客场效应 |
Python 完整案例
数据准备
import numpy as np
import pandas as pd
from scipy import stats
# 模拟:A队 vs B队 10 次交锋数据
data = {
'match': range(1, 11),
'A_goals': [2, 1, 3, 1, 2, 0, 2, 1, 1, 2],
'B_goals': [1, 1, 1, 2, 0, 1, 1, 1, 0, 1],
'A_xG': [1.8, 1.2, 2.5, 1.1, 1.9, 0.8, 1.7, 1.3, 1.0, 1.6],
'B_xG': [1.0, 0.9, 1.2, 1.5, 0.7, 1.3, 1.1, 1.0, 0.8, 0.9],
'A_shots': [15, 12, 18, 10, 14, 8, 16, 11, 9, 13],
'B_shots': [10, 9, 11, 13, 7, 12, 10, 9, 8, 10],
}
df = pd.DataFrame(data)
print(df)
基础统计对比
def summarize(df):
result = {}
for team in ['A', 'B']:
result[team] = {
'场均进球': df[f'{team}_goals'].mean(),
'场均xG': df[f'{team}_xG'].mean(),
'场均射门': df[f'{team}_shots'].mean(),
'进球标准差': df[f'{team}_goals'].std(),
}
return pd.DataFrame(result)
summary = summarize(df)
summary['差值(A-B)'] = summary['A'] - summary['B']
print(summary.round(2))
输出示例:
A B 差值(A-B)
场均进球 1.50 0.90 0.60
场均xG 1.59 1.04 0.55
场均射门 12.60 9.90 2.70
进球标准差 0.85 0.57 0.28
统计显著性检验(真实差距是否显著)
# 独立样本 t 检验:进球差异是否显著
t_stat, p_value = stats.ttest_ind(df['A_goals'], df['B_goals'])
print(f"t = {t_stat:.3f}, p = {p_value:.4f}")
# 用 xG 做检验(更稳定)
t_xg, p_xg = stats.ttest_ind(df['A_xG'], df['B_xG'])
print(f"xG: t = {t_xg:.3f}, p = {p_xg:.4f}")
# 效应量 Cohen's d
def cohens_d(x, y):
pooled_std = np.sqrt((x.std()**2 + y.std()**2) / 2)
return (x.mean() - y.mean()) / pooled_std
d = cohens_d(df['A_xG'], df['B_xG'])
print(f"Cohen's d = {d:.2f}")
解读标准:
- p < 0.05 → 差距统计显著
- Cohen's d: 0.2 小 / 0.5 中 / 0.8 大
贝叶斯估计(推荐方法)
单场比分波动大,用贝叶斯能给出真实差距的概率分布:
import pymc as pm
import arviz as az
with pm.Model() as model:
# 先验:两队真实进攻强度
mu_A = pm.Normal('mu_A', mu=1.5, sigma=1)
mu_B = pm.Normal('mu_B', mu=1.5, sigma=1)
# 观测似然(泊松分布适合进球数据)
goals_A = pm.Poisson('goals_A', mu=mu_A, observed=df['A_goals'])
goals_B = pm.Poisson('goals_B', mu=mu_B, observed=df['B_goals'])
# 关键:计算实力差距
diff = pm.Deterministic('diff', mu_A - mu_B)
trace = pm.sample(2000, return_inferencedata=True)
az.summary(trace, var_names=['mu_A', 'mu_B', 'diff'])
输出解读:
mean sd hdi_3% hdi_97%
mu_A 1.52 0.38 0.82 2.24
mu_B 0.93 0.30 0.38 1.50
diff 0.59 0.48 -0.34 1.51
diff的均值 ≈ 59 球- HDI 区间跨 0 → 差距存在但不绝对确定
Elo 评分法(长期真实实力)
def update_elo(rating_a, rating_b, score_a, k=20):
"""score_a: 1=胜, 0.5=平, 0=负"""
expected_a = 1 / (1 + 10**((rating_b - rating_a) / 400))
new_a = rating_a + k * (score_a - expected_a)
new_b = rating_b + k * ((1 - score_a) - (1 - expected_a))
return new_a, new_b
# 初始 1500
ra, rb = 1500, 1500
for _, row in df.iterrows():
if row['A_goals'] > row['B_goals']:
s = 1
elif row['A_goals'] < row['B_goals']:
s = 0
else:
s = 0.5
ra, rb = update_elo(ra, rb, s)
print(f"A队 Elo: {ra:.1f}")
print(f"B队 Elo: {rb:.1f}")
print(f"实力差距: {ra - rb:.1f} 分")
Elo 差距 → 胜率换算:
def win_probability(rating_diff):
return 1 / (1 + 10**(-rating_diff / 400))
print(f"A队胜率: {win_probability(ra - rb):.1%}")
如何判断"真实差距"
def real_gap(df):
"""综合评估两队真实实力差距"""
report = {}
# 1. 进球差
report['进球差(场均)'] = df['A_goals'].mean() - df['B_goals'].mean()
# 2. xG 差(更可信)
report['xG差(场均)'] = df['A_xG'].mean() - df['B_xG'].mean()
# 3. 显著性
_, p = stats.ttest_ind(df['A_xG'], df['B_xG'])
report['p值'] = p
report['显著'] = '✅ 显著' if p < 0.05 else '❌ 不显著'
# 4. 效应量
report["Cohen's d"] = cohens_d(df['A_xG'], df['B_xG'])
return report
import pprint
pprint.pprint(real_gap(df))
举例输出:
{'进球差(场均)': 0.6,
'xG差(场均)': 0.55,
'p值': 0.0012,
'显著': '✅ 显著',
"Cohen's d": 1.82}
- A 队场均多进 6 球,xG 多 55
- p = 0.0012 < 0.05 → 差距统计显著
- Cohen's d = 1.82 → 效应量很大
- 👉 A 队真实实力明显强于 B 队
关键要点总结
- 单场比分不可靠 —— 必须多场综合
- xG 比进球更稳定 —— 剔除运气
- 要检验显著性 —— 差异可能是随机波动
- 贝叶斯给出概率分布 —— 而不是单一数字
- Elo 用于长期实力 —— 反映稳定水平
- 同时看效应量和 p 值 —— 避免被大样本误导
真实差距 = 期望值差 + 显著性检验 + 效应量大小 + 概率分布,四者综合才能下结论。
版权声明: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直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播