python案例如何看让球胜平负的分布?

wen python案例 3

本文目录导读:

python案例如何看让球胜平负的分布?

  1. 数据准备
  2. 完整分析代码
  3. 进阶分析:赔率隐含概率 vs 实际概率
  4. 关键结论解读
  5. 实战建议

我来给你一个完整的Python案例,分析足球让球胜平负的分布情况。

数据准备

假设你有类似这样的盘口数据(CSV格式):

match_id,home_team,away_team,handicap,home_odds,draw_odds,away_odds,result
1,曼城,阿森纳,-1.0,1.85,3.60,4.20,H
2,利物浦,切尔西,-0.5,1.95,3.40,3.80,D
3,拜仁,多特,-1.5,2.10,3.80,3.20,A
...
  • handicap:让球数(负=主让,正=客让,0=平手)
  • result:H=让球主胜,D=让球平,A=让球客胜

完整分析代码

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
# 1. 读取数据
df = pd.read_csv('handicap_data.csv')
# 2. 让球盘口分类
def classify_handicap(h):
    if h <= -1.5:  return '主让1.5+'
    elif h == -1.0: return '主让1'
    elif h == -0.75: return '主让0.75'
    elif h == -0.5: return '主让0.5'
    elif h == -0.25: return '主让0.25'
    elif h == 0:    return '平手'
    elif h == 0.25: return '客让0.25'
    elif h == 0.5:  return '客让0.5'
    elif h == 0.75: return '客让0.75'
    elif h == 1.0:  return '客让1'
    else:           return '客让1.5+'
df['handicap_cat'] = df['handicap'].apply(classify_handicap)
# 3. 整体分布
print("=== 整体让球胜平负分布 ===")
overall = df['result'].value_counts(normalize=True) * 100
print(overall.round(2))
# 4. 按让球盘口分组统计
print("\n=== 各让球盘口的胜平负分布 ===")
dist = pd.crosstab(df['handicap_cat'], df['result'], normalize='index') * 100
# 调整列顺序
dist = dist.reindex(columns=['H', 'D', 'A']).round(2)
# 加样本数
dist['样本数'] = df.groupby('handicap_cat').size()
print(dist)
# 5. 可视化:堆叠柱状图
fig, axes = plt.subplots(1, 2, figsize=(16, 6))
# 左图:各盘口分布
dist_plot = dist[['H', 'D', 'A']]
dist_plot.plot(kind='bar', stacked=True, ax=axes[0],
               color=['#e74c3c', '#95a5a6', '#3498db'], width=0.75)
axes[0].set_title('各让球盘口的胜平负分布', fontsize=14)
axes[0].set_xlabel('让球盘口')
axes[0].set_ylabel('占比 (%)')
axes[0].legend(['主胜', '平', '客胜'])
axes[0].tick_params(axis='x', rotation=45)
# 右图:整体饼图
axes[1].pie(overall.values, labels=['主胜', '平', '客胜'],
            autopct='%1.1f%%', colors=['#e74c3c', '#95a5a6', '#3498db'])
axes[1].set_title('整体让球胜平负分布', fontsize=14)
plt.tight_layout()
plt.savefig('handicap_distribution.png', dpi=150)
plt.show()
# 6. 让球方向的宏观统计
df['direction'] = np.where(df['handicap'] < 0, '主让',
                    np.where(df['handicap'] > 0, '客让', '平手'))
print("\n=== 按让球方向统计 ===")
print(pd.crosstab(df['direction'], df['result'], normalize='index').round(3) * 100)
# 7. 让球数与赛果的相关性
# 将结果编码为数值:H=-1, D=0, A=1
df['result_num'] = df['result'].map({'H': -1, 'D': 0, 'A': 1})
corr = df[['handicap', 'result_num']].corr().iloc[0, 1]
print(f"\n让球数与赛果相关系数: {corr:.3f}")
# 8. 热力图展示
plt.figure(figsize=(10, 6))
sns.heatmap(dist_plot, annot=True, fmt='.1f', cmap='RdYlGn_r',
            cbar_kws={'label': '占比 (%)'})'让球盘口 × 赛果 热力图', fontsize=14)
plt.tight_layout()
plt.savefig('handicap_heatmap.png', dpi=150)
plt.show()

进阶分析:赔率隐含概率 vs 实际概率

# 计算隐含概率(去水)
def implied_prob(row):
    odds = [row['home_odds'], row['draw_odds'], row['away_odds']]
    inv = [1/o for o in odds]
    total = sum(inv)
    return [i/total for i in inv]
df[['p_h', 'p_d', 'p_a']] = df.apply(
    lambda r: pd.Series(implied_prob(r)), axis=1)
# 按盘口对比实际与隐含概率
compare = df.groupby('handicap_cat').agg(
    实际主胜=('result', lambda x: (x=='H').mean()),
    隐含主胜=('p_h', 'mean'),
    实际平=('result', lambda x: (x=='D').mean()),
    隐含平=('p_d', 'mean'),
    实际客胜=('result', lambda x: (x=='A').mean()),
    隐含客胜=('p_a', 'mean'),
    样本数=('result', 'size')
).round(3)
print("=== 隐含概率 vs 实际概率 ===")
print(compare)
# 价值判断:实际 - 隐含 > 0 表示被低估
compare['主胜偏差'] = compare['实际主胜'] - compare['隐含主胜']
print("\n各盘口主胜被低估程度:")
print(compare['主胜偏差'].sort_values(ascending=False))

关键结论解读

运行后你会得到几个重要信息:

观察点 含义
整体分布 让球主胜通常约40-45%,让球平约25-30%,让球客胜约25-30%
深盘(让1.5+) 主胜概率显著升高,但赔率低
浅盘(让0.25/0.5) 分布最接近,价值最需挖掘
受让盘 客胜/平比例上升
偏差分析 实际-隐含 > 0 的盘口存在"价值"

实战建议

  1. 样本量要够:每个盘口至少50场才有统计意义
  2. 分联赛分析:不同联赛让球分布差异大(如德甲大球多、意甲小球多)
  3. 结合大小球:让球方向+总进球能提升判断精度
  4. 动态监控:初盘→终盘的变化本身就是信号(升降盘)

需要我针对某个具体环节(比如爬取数据、凯利公式计算、时间序列走势)深入展开吗?

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