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

如何加速DataFrame迭代?R语言实现销售额均分的代码优化求助

问题描述

样本数据

ACCOUNT_KEY                    SG         Total_sales
C9240000000000440             1.LOYAL++   84000.000
C9240000000000067           3.COMMITTED   35723.356
C9240000000000840         7.NEW JOINERS   26492.515
C9240000000000254       11.PROFESSIONAL   21598.651
C9240000000000027       11.PROFESSIONAL   21412.302
C9240000000000008          5.FRESH FOOD   16849.033
C9240000000000662       11.PROFESSIONAL   16005.060
C920000000000479             1.LOYAL++    15374.671

需要将上述DataFrame划分为TG和CG两个子集,使两者的Total_sales总和尽可能接近。当前使用的R代码因循环逻辑导致耗时过长,请求优化以提升速度。

原实现代码

dataframe2 <- dataframe[order(-dataframe$Total_sales),]
dataframe2$ACCOUNT_KEY = as.factor(dataframe2$ACCOUNT_KEY)
dataframe2$SG = as.factor(dataframe2$SG)

rm(TG)
rm(CG)
summary(dataframe2)

CG = head(dataframe2,1)
dataframe2 = dataframe2[-1,]
TG = head(dataframe2,1)
dataframe2 = dataframe2[-1,]

j = 2
k = 2

for (i in 1 : nrow(dataframe2)) 
{
if (sum(TG$Total_sales) < sum(CG$Total_sales))
{
  TG[j,] = dataframe2[i,]
  j = j+1
}
else
{  
  CG[k,] = dataframe2[i,]
  k = k+1
}
}
优化方案

问题根源

原代码效率低的核心原因:

  • 每次循环都重新计算整个TG/CG的Total_sales总和,随着数据量增大,重复计算的开销呈指数级增长
  • 逐行手动扩充数据框的操作在R中效率极低,频繁的行绑定会产生大量内存拷贝,拖慢执行速度

优化思路

  1. 跟踪总和而非重复计算:维护两个变量实时记录TG和CG的当前总和,避免每次循环遍历整个列求和
  2. 用标记向量替代逐行修改:先创建一个分组标记向量,最后一次性拆分数据框,减少内存操作开销
  3. 保留贪心策略:原代码的贪心逻辑(每次将下一个元素分配到总和较小的组)是合理的,继续沿用该逻辑但优化执行方式

优化后代码

# 保持原逻辑的数据排序
dataframe2 <- dataframe[order(-dataframe$Total_sales),]
dataframe2$ACCOUNT_KEY <- as.factor(dataframe2$ACCOUNT_KEY)
dataframe2$SG <- as.factor(dataframe2$SG)

# 初始化分组标记向量和总和变量
group_tag <- character(nrow(dataframe2))
group_tag[1] <- "CG"
group_tag[2] <- "TG"

sum_cg <- dataframe2$Total_sales[1]
sum_tg <- dataframe2$Total_sales[2]

# 遍历剩余数据行(从第3行开始)
for (i in 3:nrow(dataframe2)) {
  if (sum_tg < sum_cg) {
    group_tag[i] <- "TG"
    sum_tg <- sum_tg + dataframe2$Total_sales[i]
  } else {
    group_tag[i] <- "CG"
    sum_cg <- sum_cg + dataframe2$Total_sales[i]
  }
}

# 一次性拆分得到TG和CG
TG <- dataframe2[group_tag == "TG", ]
CG <- dataframe2[group_tag == "CG", ]

# 验证结果
cat("TG总销售额:", sum_tg, "\n")
cat("CG总销售额:", sum_cg, "\n")

大数据量场景进阶优化

如果数据集规模很大(如十万行以上),可以使用data.table进一步提升效率,它的内存操作和循环性能比基础R更优:

library(data.table)

# 转换为data.table格式
dt <- as.data.table(dataframe)
# 按销售额降序排序
dt <- dt[order(-Total_sales)]
# 转换因子类型
dt[, ACCOUNT_KEY := as.factor(ACCOUNT_KEY)]
dt[, SG := as.factor(SG)]

# 初始化分组标记和总和
dt[, group := ""]
dt[1, group := "CG"]
dt[2, group := "TG"]

sum_cg <- dt[1, Total_sales]
sum_tg <- dt[2, Total_sales]

# 遍历分配分组
for (i in 3:nrow(dt)) {
  if (sum_tg < sum_cg) {
    dt[i, group := "TG"]
    sum_tg <- sum_tg + dt[i, Total_sales]
  } else {
    dt[i, group := "CG"]
    sum_cg <- sum_cg + dt[i, Total_sales]
  }
}

# 拆分得到结果
TG <- dt[group == "TG"]
CG <- dt[group == "CG"]

优化效果说明

  • 时间复杂度从原代码的O(n²)降至O(n),避免了重复求和的开销
  • 减少了大量内存拷贝操作,向量标记+一次性拆分的方式更符合R的内部优化逻辑
  • 代码逻辑更简洁易懂,维护成本更低

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 18:36:26