如何按ID合并数据框指定分组的行并对num_to_sum列求和?
解决方案:按指定分组合并并聚合数据
示例数据构造
先模拟符合你描述的数据集:
set.seed(123) df <- data.frame( group = rep(c("group1", "group2", "group3"), each = 100), ID = rep(sprintf("%02d", 1:100), 3), feat2 = rep(sample(1:100, 100), 3), feat3 = rep(sample(letters, 100), 3), num_to_sum = rnorm(300, 50, 10) )
方法一:用dplyr实现灵活分组合并
这种方式支持合并任意数量的分组,只需修改分组映射规则:
library(dplyr) # 定义分组映射:键是新分组名,值是需要合并的原分组集合 group_mapping <- list( group12 = c("group1", "group2"), # 合并group1和group2为group12 group3 = "group3" # 保留原分组group3 ) # 反转映射,将原分组匹配到对应的新分组 reverse_map <- stack(group_mapping) %>% rename(old_group = values, new_group = ind) # 执行合并与聚合 result_df <- df %>% left_join(reverse_map, by = c("group" = "old_group")) %>% group_by(new_group, ID) %>% summarise( num_to_sum = sum(num_to_sum), # 同一ID的feat2/feat3值一致,取任意一个即可 feat2 = first(feat2), feat3 = first(feat3), .groups = "drop" ) # 如果不需要feat2/feat3,直接筛选列即可 result_df_no_feats <- result_df %>% select(new_group, ID, num_to_sum)
方法二:用data.table实现高效处理(适合大数据)
如果你的数据集规模较大,data.table的性能更优:
library(data.table) setDT(df) # 同样定义分组映射 group_mapping <- list( group12 = c("group1", "group2"), group3 = "group3" ) reverse_map <- melt(group_mapping, value.name = "old_group", variable.name = "new_group") # 合并并聚合 result_dt <- df[reverse_map, on = c(group = "old_group")][, .( num_to_sum = sum(num_to_sum), feat2 = first(feat2), feat3 = first(feat3) ), by = .(new_group, ID)] # 去掉feat列的版本 result_dt_no_feats <- result_dt[, .(new_group, ID, num_to_sum)]
为什么stats::aggregate难以实现?
aggregate的聚合逻辑相对固定,无法直接自定义多分组到新分组的映射规则,而上述方法通过先建立分组映射关系,再按新分组+ID聚合的思路,完美解决了带条件的合并需求,且支持任意数量的分组合并。
内容的提问来源于stack exchange,提问作者j3141592653589793238
相关产品推荐
相关产品推荐

