如何用dplyr批量计算tibble中各列的分组均值差?
批量计算分组均值差异的简洁方法
你有一个包含约100个变量列的tibble,需要按groupID分组计算每个变量的均值差异,目前只能逐列处理,希望一次性完成所有列的计算。
逐列处理的示例代码
library(tidyverse) foo <- tibble(var1 = rnorm(100), var2 = rnorm(100), var3 = rnorm(100), groupID = rep(c("A","B"),50)) # 让其中一个变量组间有差异作为示例 foo <- foo %>% mutate(var3 = case_when(groupID=="A" ~ var3 + 1, groupID=="B" ~ var3 - 1)) res <- bind_rows(foo %>% group_by(groupID) %>% summarise(avg = mean(var1)) %>% summarise(meanDiff = diff(avg)), foo %>% group_by(groupID) %>% summarise(avg = mean(var2)) %>% summarise(meanDiff = diff(avg)), foo %>% group_by(groupID) %>% summarise(avg = mean(var3)) %>% summarise(meanDiff = diff(avg))) res
更简洁的批量处理方法
利用tidyverse的across()函数可以一次性对所有目标列执行计算,无需逐列重复代码:
方法一:清晰分步写法
library(tidyverse) foo <- tibble(var1 = rnorm(100), var2 = rnorm(100), var3 = rnorm(100), groupID = rep(c("A","B"),50)) %>% mutate(var3 = case_when(groupID == "A" ~ var3 + 1, groupID == "B" ~ var3 - 1)) res <- foo %>% # 按分组计算所有非groupID列的均值 group_by(groupID) %>% summarise(across(-groupID, mean)) %>% # 转长格式便于后续计算差异 pivot_longer(-groupID, names_to = "variable", values_to = "avg") %>% # 转回宽格式,把两组均值放在同一行 pivot_wider(names_from = groupID, values_from = avg) %>% # 计算组间均值差异 mutate(meanDiff = A - B) %>% # 保留需要的列 select(variable, meanDiff) res
方法二:紧凑写法
res <- foo %>% group_by(groupID) %>% summarise(across(-groupID, mean)) %>% ungroup() %>% pivot_longer(-groupID) %>% group_by(name) %>% # 利用diff计算两组均值的差异(注意diff的顺序由groupID的排序决定) summarise(meanDiff = diff(value)) res
优化你的现有方案
你自己的转长格式方法是可行的,但可以简化为上述紧凑写法,减少提前转长的步骤,同时保持代码的可读性,更适合处理大量变量的场景。
内容的提问来源于stack exchange,提问作者user111024
相关产品推荐
相关产品推荐

