Python循环传值给poisson.pmf计算足球赛进球概率的问题求解
报错原因
你出现维度不匹配报错的核心原因是把np.clip返回的Series额外套了一层列表,导致xG参数的维度和进球数数组维度无法对齐广播。另外手动定义每个比分变量的方式冗余度极高,我们可以通过numpy广播特性一次性计算所有比分的概率。
优化后完整代码
import numpy as np import pandas as pd from scipy.stats import poisson # 配置参数 max_goals = 5 # 最多计算到双方各进5球 goals_arr = np.arange(max_goals + 1) # 处理xG参数,调整为(比赛数, 1)的二维数组适配广播规则 home_xg = np.clip(xG_fixtures['home_xG'], 1.0, None).values.reshape(-1, 1) away_xg = np.clip(xG_fixtures['away_xG'], 1.0, None).values.reshape(-1, 1) # 批量计算所有比分的概率,输出形状为 [比赛数, 主场进球数, 客场进球数] home_pmf = poisson.pmf(goals_arr, home_xg) away_pmf = poisson.pmf(goals_arr, away_xg) all_score_probs = np.einsum('nc, nr -> ncr', home_pmf, away_pmf) * 100 # 初始化结果表 predict_outcome = xG_fixtures[['fixture.id', 'teams.home.name', 'teams.away.name']].copy() # 批量添加所有比分对应概率列 for hg in goals_arr: for ag in goals_arr: if hg > ag: cate = 'home' elif hg == ag: cate = 'draw' else: cate = 'away' col_name = f"{cate} {hg} - {ag}" predict_outcome[col_name] = all_score_probs[:, hg, ag] # 汇总三类结果概率 predict_outcome['home %'] = predict_outcome.filter(like='home ').sum(axis=1) predict_outcome['draw %'] = predict_outcome.filter(like='draw ').sum(axis=1) predict_outcome['away %'] = predict_outcome.filter(like='away ').sum(axis=1) # 输出结果 print(predict_outcome)
代码说明
- 把xG数组调整为
(比赛数, 1)的二维结构后,和长度为6的进球数数组计算时,numpy会自动扩展维度完成广播,不会再出现维度不匹配的报错 - 使用
einsum一次性计算所有场次所有比分的联合概率,避免手动写每个比分的计算逻辑 - 双层循环自动生成所有比分的列名并赋值,后续如果要调整最多计算的进球数,只需要修改
max_goals参数即可,不需要修改其他逻辑 - 汇总概率用
filter方法直接筛选对应前缀的列,逻辑更简洁
内容的提问来源于stack exchange,提问作者Thomas Batelaan
相关产品推荐
相关产品推荐

