如何用dplyr的across函数实现分组t检验,替代弃用的summarize_each
正确实现方案
版本1:和旧方案输出完全一致
library(tidyverse) library(broom) mtcars %>% group_by(am) %>% summarise(across( .cols = mpg, .fns = list( p.value = ~ t.test(.x[cur_data()$vs == 0], .x[cur_data()$vs == 1])$p.value, conf.low = ~ t.test(.x[cur_data()$vs == 0], .x[cur_data()$vs == 1])$conf.int[1], conf.high = ~ t.test(.x[cur_data()$vs == 0], .x[cur_data()$vs == 1])$conf.int[2] ) ))
运行输出:
# A tibble: 2 × 4 am mpg_p.value mpg_conf.low mpg_conf.high <dbl> <dbl> <dbl> <dbl> 1 0 0.000395 -8.33 -3.05 2 1 0.00459 -14.0 -3.27
如果需要批量处理多个指标,只要修改.cols参数即可,比如.cols = c(mpg, disp, hp)就能同时对这三个指标做分组t检验。
版本2:更简洁的完整结果输出(推荐)
直接用broom::tidy提取t检验的所有结果,无需手动逐个提取字段:
mtcars %>% group_by(am) %>% summarise( across(mpg, ~ list(tidy(t.test(.x[vs == 0], .x[vs == 1])))) %>% unnest(everything()) )
运行输出会包含t检验的统计量、估计值、p值、置信区间、检验方法等全部字段,和单独调用t.test后tidy的结果完全一致。
报错原因说明
你之前的代码有两个核心问题:
across的.fns参数要求接收函数对象,你直接传入了执行表达式,没有封装为函数。需要用~开头的purrr风格lambda表达式封装逻辑。across的lambda中,.x(或者简写的.)仅指代当前遍历的列(也就是你选中的mpg向量),无法直接访问同分组的其他列,需要用cur_data()获取当前分组的完整数据框,才能调用vs列做筛选。
内容的提问来源于stack exchange,提问作者Ryan John
相关产品推荐
相关产品推荐

