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

R语言百万级数据表高效计算月度猜测组合最优得分方案

问题背景

我现在有两个数据表:

  • 数据表dt1记录了最近N年各月份的销量数据,示例如下:
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
 1:  35  46  37  14  13   6  38  25  12  42  10  43
 2:   3  36  20  32  18  48  42  27  38  48  15  34
 3:  11  40  49  19  50   5   9  38   8  12  45  40
  • 数据表dt2存储了所有员工的3个月份猜测记录,示例如下:
Guess1 Guess2 Guess3
 1:    Nov    Aug    Oct
 2:    Oct    Jan    Jul
 3:    Sep    May    Jun

需求说明

对每一年的销量数据,计算所有猜测组合对应的3个月份销量总和,给总分最高的猜测组合得分加1。当前两个数据表均为百万级记录,需要最高效的实现方案。

原有实现(存在严重性能问题)

set.seed(1)
dt1 = as.data.table(replicate(12,sample(1:50,replace=F)))
setnames(dt1, month.abb)
set.seed(1)
dt2 = data.table(Guess1=sample(month.abb, 10), Guess2=sample(month.abb, 10), Guess3=sample(month.abb, 10))
dt2[, `:=` (Total = 0, Score = 0)]
for (i in 1:nrow(dt1)){
  thisRowAnswer = dt1[i]
  
  for(j in 1:nrow(dt2)){
    thisGuess1 = dt2[j, Guess1]
    thisGuess2 = dt2[j, Guess2]
    thisGuess3 = dt2[j, Guess3]
    # thisRowAnswer[, ..thisGuess1] works but thisRowAnswer[, ..dt2[j, Guess1]] does not
    dt2[j, "Total"] = thisRowAnswer[, ..thisGuess1][[1]] +  thisRowAnswer[, ..thisGuess2][[1]] +  thisRowAnswer[, ..thisGuess3][[1]]
  }
  
  maxTotal = max(dt2$Total)
  # Increment score for the highest total
  dt2[Total == maxTotal, Score := Score + 1]
}

# The winner is the person with the highest Score

原有代码是双重循环逻辑,时间复杂度为O(nrow(dt1)*nrow(dt2)),两个表都是百万级的情况下运算量达万亿级,完全无法正常运行。


高性能优化方案

核心思路

完全抛弃R层循环,利用向量化运算和data.table原生的高性能特性,把时间复杂度降到线性级,适配百万级数据量。

优化代码

library(data.table)

# 1. 预处理:把月份映射为数字索引,仅需执行一次
month_map = setNames(1:12, month.abb)
# 给每个猜测增加索引列和唯一id
dt2[, c("g1_idx", "g2_idx", "g3_idx", "guess_id") := .(
  month_map[Guess1], month_map[Guess2], month_map[Guess3], .I
)]

# 2. dt1转矩阵,方便批量索引取值
mat1 = as.matrix(dt1)
# 3. 批量计算所有猜测每年的总销量,得到N行M列的矩阵(N是年数,M是猜测数)
total_mat = mat1[, dt2$g1_idx] + mat1[, dt2$g2_idx] + mat1[, dt2$g3_idx]
# 4. 标记每年得分最高的猜测
max_pos = total_mat == apply(total_mat, 1, max)
# 5. 统计每个猜测的总得分,合并回dt2
score_dt = data.table(guess_id = 1:nrow(dt2), Score = colSums(max_pos))
dt2 = score_dt[dt2, on = "guess_id"]

# 最终dt2的Score列就是每个猜测的总得分,取最大值即为获胜者

性能说明

所有运算都调用底层C实现,比R层循环快至少3个数量级,百万级数据在普通服务器上仅需数秒到数十秒即可跑完,内存占用也在可控范围内。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 21:48:03