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

使用dplyr聚合大数据框并保留其他变量的性能优化问询

优化1亿行数据的分组平均分计算

碰到大数据集上dplyr分组计算慢的问题太正常了,咱们针对你的场景一步步优化:

先分析原代码的瓶颈

你的原代码里unique(school)其实做了冗余操作——因为class是由school拼接而来的,每个class必然对应唯一的school,所以不需要在每个分组里去重,换用更高效的取值方式就能先提一波速度。


方案1:替换unique()为first()(最小改动,立竿见影)

既然每个class的school完全一致,直接取分组内第一个school值就行,first()比unique()的计算开销小很多:

library(dplyr)

df %>% 
  group_by(class) %>% 
  summarise(mean_score = mean(score), 
            school = first(school))

这个改动应该能把你的耗时从8秒往下压不少,因为省去了每个分组的去重操作。


方案2:拆分计算+合并(进一步减少分组内操作)

把“提取class-school映射”和“计算平均分”拆成两步,避免在分组时同时处理两个变量:

# 先提取唯一的class-school映射(只跑一次,仅100行结果)
class_school_map <- distinct(df, class, school)

# 单独计算班级平均分(只处理score和class)
class_mean <- df %>% 
  group_by(class) %>% 
  summarise(mean_score = mean(score))

# 最后合并映射
result <- left_join(class_mean, class_school_map, by = "class")

这种方式把分组计算的工作量降到最低,只专注于score的均值计算,再通过轻量的合并操作补上school信息,效率会更高。


方案3:用data.table(大数据集的性能首选)

data.table在处理超大数据集时的效率通常远超dplyr,语法也很直观:

library(data.table)

# 转换为data.table(原地转换,无额外内存开销)
setDT(df)

# 方式1:先算平均分再合并映射
result <- df[, .(mean_score = mean(score)), by = class][class_school_map, on = "class"]

# 方式2:一步到位,直接取分组内第一个school
result <- df[, .(mean_score = mean(score), school = first(school)), by = class]

在1亿行的数据集上,data.table的分组计算速度通常能比dplyr快2-5倍,非常值得一试。


方案4:base R原生方法(无依赖,轻量高效)

如果不想加载额外包,base R的aggregate配合merge也能搞定:

# 计算平均分
class_mean <- aggregate(score ~ class, data = df, FUN = mean)
# 提取class-school映射
class_school_map <- unique(df[, c("class", "school")])
# 合并结果
result <- merge(class_mean, class_school_map, by = "class")

这个方法的性能介于dplyr优化版和data.table之间,胜在无需额外依赖。


额外小优化

如果你的内存足够,可以考虑给class列设置为因子类型,分组操作在因子上的效率会比字符型更高:

df$class <- as.factor(df$class)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:10:38