如何在单条dplyr管道中两次调用distinct等函数完成数据聚合
单管道实现方案
你不需要拆分数据集生成df1/df2两个中间变量,也不需要在distinct()后恢复原始数据,核心思路是提前在原始数据集上标记不同去重规则下的保留行,再一次性完成分组汇总,全程可以在单条管道内跑完,无重复代码。
最简实现(无额外依赖,和原代码输出完全一致)
直接用duplicated()标记两个去重规则对应的保留行,分组后分别计算均值即可:
library(dplyr) final_result <- iris %>% mutate( # 标记distinct(Species, .keep_all = TRUE)对应的保留行 keep_for_mean1 = !duplicated(Species), # 标记distinct(Species, Petal.Width, .keep_all = TRUE)对应的保留行 keep_for_mean2 = !duplicated(paste(Species, Petal.Width)) ) %>% group_by(Petal.Width) %>% summarise( Sepal.Length.mean1 = mean(Sepal.Length[keep_for_mean1]), Sepal.Length.mean2 = mean(Sepal.Length[keep_for_mean2]), .groups = "drop" )
这个写法全程不会修改原始数据集的行,只是给行加了逻辑标记,自然不存在distinct()后无法恢复初始数据的问题,代码重复度为0,可读性也比拆分中间表更高。
多规则扩展写法
如果后续需要新增更多不同去重粒度的汇总逻辑,可以用列表批量传入去重规则,自动处理后合并结果,同样全程单管道:
library(dplyr) library(purrr) final_result <- list( mean1 = "Species", mean2 = c("Species", "Petal.Width") ) %>% imap(~{ iris %>% distinct(across(all_of(.x)), .keep_all = TRUE) %>% group_by(Petal.Width) %>% summarise("Sepal.Length.{.y}" := mean(Sepal.Length), .groups = "drop") }) %>% reduce(inner_join, by = "Petal.Width")
这个写法适合3种及以上去重规则的场景,如果只有2种规则,优先用第一种标记法,逻辑更直观。
内容的提问来源于stack exchange,提问作者monotonic
相关产品推荐
相关产品推荐

