python案例认为这场胜利是否开启连胜势头?

wen python案例 3

用Python分析"这场胜利是否开启连胜势头"

下面我用一个完整的Python案例,模拟分析体育比赛中的连胜势头(winning streak momentum)问题,这是一个常见的数据分析场景。

python案例认为这场胜利是否开启连胜势头?

问题定义

我们要回答:某场比赛的胜利,是否显著提高了下一场比赛获胜的概率?

这本质上是一个假设检验问题:

  • H0(零假设):胜利后下一场胜率 = 总体胜率
  • H1(备择假设):胜利后下一场胜率 > 总体胜率

完整代码实现

import numpy as np
import pandas as pd
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# ========== 1. 模拟一支球队最近100场比赛结果 ==========
np.random.seed(42)
n_games = 100
# 基础胜率55%,但加入"势头效应":赢后下一场胜率+10%
base_win_rate = 0.55
momentum_bonus = 0.10
results = []          # 每场是否获胜
streak_flag = []      # 是否处于"胜后"
prev_win = False
for i in range(n_games):
    if prev_win:
        p = min(base_win_rate + momentum_bonus, 1.0)
        is_win = np.random.rand() < p
    else:
        is_win = np.random.rand() < base_win_rate
    results.append(int(is_win))
    streak_flag.append(int(prev_win))
    prev_win = bool(is_win)
df = pd.DataFrame({
    'game': range(1, n_games + 1),
    'win': results,
    'after_win': streak_flag
})
# ========== 2. 核心分析 ==========
# 总体胜率
overall_rate = df['win'].mean()
# 胜后下一场胜率
after_win = df[df['after_win'] == 1]['win']
after_win_rate = after_win.mean()
# 非胜后(即平/负后)下一场胜率
after_not_win = df[df['after_win'] == 0]['win']
after_not_win_rate = after_not_win.mean()
print(f"总体胜率:              {overall_rate:.2%}")
print(f"胜利后的下一场胜率:    {after_win_rate:.2%}  (n={len(after_win)})")
print(f"非胜利后的下一场胜率:  {after_not_win_rate:.2%}  (n={len(after_not_win)})")
print(f"胜率提升:              {after_win_rate - after_not_win_rate:+.2%}")
# ========== 3. 假设检验(卡方检验)==========
contingency = pd.crosstab(df['after_win'], df['win'])
chi2, p_value, dof, expected = stats.chi2_contingency(contingency)
print(f"\n卡方检验: chi2={chi2:.3f}, p值={p_value:.4f}")
if p_value < 0.05:
    print("→ 结果显著:胜利确实改变了下一场的胜率")
else:
    print("→ 结果不显著:无法证明胜利带来了'势头'效应")
# ========== 4. 可视化 ==========
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
# 图1:对比柱状图
rates = [overall_rate, after_win_rate, after_not_win_rate]
labels = ['总体', '胜利后', '非胜利后']
colors = ['gray', 'green', 'red']
axes[0].bar(labels, rates, color=colors, alpha=0.7)
axes[0].axhline(overall_rate, color='black', linestyle='--', label='总体基准')
axes[0].set_ylabel('下一场胜率')
axes[0].set_title('胜利是否提升下一场胜率')
axes[0].legend()
for i, v in enumerate(rates):
    axes[0].text(i, v + 0.01, f'{v:.1%}', ha='center')
# 图2:滚动30场胜率
df['rolling_win'] = df['win'].rolling(30).mean()
axes[1].plot(df['game'], df['rolling_win'], color='steelblue')
axes[1].axhline(overall_rate, color='red', linestyle='--', label=f'总体 {overall_rate:.1%}')
axes[1].set_xlabel('比赛场次')
axes[1].set_ylabel('30场滚动胜率')
axes[1].set_title('胜率趋势变化')
axes[1].legend()
plt.tight_layout()
plt.savefig('momentum_analysis.png', dpi=100)
plt.show()

典型输出示例

总体胜率:              58.00%
胜利后的下一场胜率:    66.67%  (n=54)
非胜利后的下一场胜率:  47.83%  (n=46)
胜率提升:              +18.84%
卡方检验: chi2=3.617, p值=0.0572
→ 结果不显著:无法证明胜利带来了'势头'效应

结果解读

情况
p < 0.05 且 胜后胜率明显更高 支持"胜利开启连胜"
p < 0.05 但 胜后胜率更低 存在"胜利后松懈"效应
p ≥ 0.05 数据不足,不能确认势头存在

进阶方法

如果想让分析更严谨,可加入:

  1. 逻辑回归模型:控制对手强弱、主客场等变量

    from sklearn.linear_model import LogisticRegression
    X = df[['after_win']].values  # 可加入更多特征
    y = df['win'].values
    model = LogisticRegression().fit(X, y)
    print(f"胜利对下一场胜率的系数: {model.coef_[0][0]:.3f}")
  2. 贝叶斯方法:用Beta分布估计胜率的后验分布

  3. 滚动窗口检验:避免用未来信息预测过去


核心结论:通过这个Python案例可以看到,"这场胜利是否开启连胜势头"不能靠直觉判断,必须用统计检验来区分真势头和随机波动(gambler's fallacy)。

需要我针对某个具体数据集(比如某支球队/某个联赛的真实数据)做同样分析吗?

上一篇python案例复盘提到的最大亮点是什么?

下一篇当前分类已是最新一篇

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