You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在R语言中为足球比赛数据框批量生成胜负平泊松概率列

问题描述

我有一个记录足球比赛及对应球队平均进球率的数据框df,前两列为主队、客队,第三、四列分别是主队、客队的平均进球率,示例如下:

Home      Away HomeRate AwayRate
1   Arsenal   Bristol      1.3      1.3
2   Chelsea Newcastle      2.4      2.3
3 Liverpool     Leeds      3.3      1.7
4    Bolton    Fulham      2.1      2.5

我希望生成三个新列HomeWin、Draw、AwayWin,分别给出每场比赛主队获胜、平局、客队获胜的泊松概率,并添加到数据框中,假设事件相互独立。

我可以手动逐个处理单场比赛,但不知道如何对整个表格批量处理。以第二行(切尔西vs纽卡斯尔)为例,手动处理代码如下:

# 生成主队进球概率(含20+球的概率)
H <- c(dpois(0:20, df[2,3]), ppois(20, df[2,3], lower.tail=FALSE))
# 生成客队进球概率(含20+球的概率)
A <- c(dpois(0:20, df[2,4]), ppois(20, df[2,3], lower.tail=FALSE))
# 生成比分概率矩阵
ProbMatrix = outer(H, A)

# 计算胜负平概率
Prob_Home_Win = sum(ProbMatrix[lower.tri(ProbMatrix)])
Prob_Away_Win = sum(ProbMatrix[upper.tri(ProbMatrix)])
Prob_Draw = sum(diag(ProbMatrix))

但如何高效地为数据框df中的所有比赛生成完整的HomeWin、AwayWin和Draw列?

解决方案

方法1:基础R apply 批量处理

把单场比赛的计算逻辑封装成函数,通过apply对数据框逐行调用,实现批量计算:

# 定义计算单场胜负平概率的函数
calc_poisson_probs <- function(row) {
  home_rate <- row["HomeRate"]
  away_rate <- row["AwayRate"]
  
  # 生成主队进球概率向量(0-20球 + 20+球的概率)
  H <- c(dpois(0:20, home_rate), ppois(20, home_rate, lower.tail = FALSE))
  # 生成客队进球概率向量(修正手动代码中的参数错误,用客队进球率)
  A <- c(dpois(0:20, away_rate), ppois(20, away_rate, lower.tail = FALSE))
  
  # 构建比分概率矩阵
  prob_matrix <- outer(H, A)
  
  # 计算三种结果的概率
  home_win <- sum(prob_matrix[lower.tri(prob_matrix)])
  away_win <- sum(prob_matrix[upper.tri(prob_matrix)])
  draw <- sum(diag(prob_matrix))
  
  # 返回命名结果向量
  return(c(HomeWin = home_win, Draw = draw, AwayWin = away_win))
}

# 对数据框的进球率列逐行应用函数,合并结果到原数据框
prob_results <- t(apply(df[, c("HomeRate", "AwayRate")], 1, calc_poisson_probs))
df <- cbind(df, prob_results)

方法2:tidyverse 逐行处理(更易读)

如果使用dplyr,可以通过rowwise()实现逐行计算,逻辑更直观:

library(dplyr)

df <- df %>%
  rowwise() %>%
  mutate(
    # 生成主队/客队进球概率列表(保留为向量)
    H = list(c(dpois(0:20, HomeRate), ppois(20, HomeRate, lower.tail = FALSE))),
    A = list(c(dpois(0:20, AwayRate), ppois(20, AwayRate, lower.tail = FALSE))),
    # 计算各结果概率
    HomeWin = sum(outer(H, A)[lower.tri(outer(H, A))]),
    AwayWin = sum(outer(H, A)[upper.tri(outer(H, A))]),
    Draw = sum(diag(outer(H, A)))
  ) %>%
  # 移除中间临时列
  select(-H, -A) %>%
  ungroup()

关键修正与说明

  • 修正了手动代码中的错误:计算客队20+球概率时,应使用客队的平均进球率AwayRate,而非主队的HomeRate,避免概率计算偏差。
  • 以20球作为进球上限,既能保证概率总和接近1,又不会因计算量过大影响效率。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 09:35:15