按分组计算多列均值与95%置信区间的报错解决问询
按分组批量计算多列均值与95%置信区间的问题解决
问题背景
需要为90余列数据按Group分组计算均值与95%置信区间(CI),示例数据如下:
| Group | A_pre | A_post | B_pre | B_post |
|---|---|---|---|---|
| 0 | 20 | 21 | 20 | 23 |
| 1 | 30 | 10 | 19 | 11 |
| 2 | 10 | 53 | 30 | 34 |
| 1 | 22 | 32 | 25 | 20 |
| 2 | 34 | 40 | 32 | 30 |
| 0 | 30 | 50 | NA | 40 |
| 0 | 39 | 40 | 19 | 20 |
| 1 | 40 | NA | 20 | 20 |
| 2 | 50 | 10 | 20 | 10 |
| 0 | 34 | 23 | 30 | 10 |
尝试使用dplyr与gmodels编写代码:
library(dplyr) library(gmodels) df <- df %>% group_by(group) %>% dplyr::summarize_all(list(~mean(., trim = 0), ~ci(.,)), na.rm=TRUE)
运行后报错:
Error in UseMethod("ci") : no applicable method for 'ci' applied to an object of class "c('grouped_df', 'tbl_df', 'tbl', 'data.frame')"
目前使用rcompanion包的groupwiseMean函数仅能逐列计算CI,处理90余列效率极低,需解决gmodels的报错或寻找其他高效方案。
方案1:修复gmodels::ci的调用问题
gmodels::ci函数默认接收向量而非数据框列,在dplyr中需确保传入的是向量。推荐使用across(dplyr1.0.0+的推荐函数,替代summarize_all),并拆分置信区间为上下限列:
library(dplyr) library(gmodels) df <- df %>% group_by(Group) %>% summarize(across(everything(), list(mean = ~mean(., na.rm = TRUE), ci_lower = ~ci(., na.rm = TRUE)[1], ci_upper = ~ci(., na.rm = TRUE)[2]), .names = "{.col}_{.fn}"))
该代码会为每列生成列名_mean、列名_ci_lower、列名_ci_upper三列结果,自动处理NA值。
方案2:基于t.test的tidyverse批量处理
利用t.test内置的置信区间计算,配合broom整理结果,适合多列批量处理:
library(dplyr) library(tidyr) library(broom) # 转换为长格式,统一处理所有数值列 df_long <- df %>% pivot_longer(cols = -Group, names_to = "variable", values_to = "value") # 分组计算均值与95%CI result <- df_long %>% group_by(Group, variable) %>% summarize(tidy(t.test(value, conf.level = 0.95)), .groups = "drop") %>% select(Group, variable, mean = estimate, ci_lower = conf.low, ci_upper = conf.high) # 可选:转回宽格式,匹配原数据列结构 result_wide <- result %>% pivot_wider(names_from = variable, values_from = c(mean, ci_lower, ci_upper), names_sep = "_")
长格式处理避免了逐列操作的低效,90列数据的转换和计算速度显著提升。
方案3:data.table超高效处理
如果数据量极大,data.table的向量化处理效率远超传统循环:
library(data.table) library(gmodels) setDT(df) # 按Group分组,批量计算每列的均值与CI result <- df[, lapply(.SD, function(x) { m <- mean(x, na.rm = TRUE) ci_vals <- ci(x, na.rm = TRUE) list(mean = m, ci_lower = ci_vals[1], ci_upper = ci_vals[2]) }), by = Group] # 展开列表列,得到扁平结构的结果 result <- result[, unlist(.SD, recursive = FALSE), by = Group]
data.table的lapply(.SD, ...)会对所有非分组列(即90余列数值列)批量执行计算,无需手动循环。
内容的提问来源于stack exchange,提问作者amir.fathi
相关产品推荐
相关产品推荐

