如何在R语言中为数据框各列提取基于分组的p值?
批量计算分组t检验统计量及p值
问题背景
现有如下数据框:
df = structure(list(aa = c(1L, 5L, 8L, 10L, 1L, 10L, 8L, 6L, 7L, 4L, 1L, 5L, 7L, 7L, 5L, 8L), bb = c(2L, 9L, 1L, 10L, 8L, 7L, 10L, 8L, 1L, 7L, 2L, 10L, 3L, 5L, 2L, 10L), cc = c(1L, 5L, 9L, 4L, 9L, 1L, 8L, 3L, 2L, 2L, 2L, 5L, 7L, 2L, 2L, 3L), dd = c(10L, 5L, 8L, 10L, 6L, 8L, 7L, 5L, 2L, 9L, 10L, 6L, 5L, 3L, 7L, 8L), ee = c(5L, 7L, 5L, 1L, 8L, 4L, 5L, 2L, 10L, 6L, 8L, 10L, 6L, 5L, 10L, 6L), Group = c("High", "High", "High", "High", "High", "High", "High", "High", "Low", "Low", "Low", "Low", "Low", "Low", "Low", "Low")), class = "data.frame", row.names = c(NA, -16L))
需要基于Group列,为每一列(aa、bb、cc、dd、ee)批量计算t检验的p值、t值,以及两组的均值,预期输出格式如下:
values pvalue t mean in High mean in Low aa 0.08 0.41523 6.8 5 bb 0.89 1.41523 6.8 4 cc 0.088 2.41523 2.3 8 dd 0.89 3.41523 9.6 2 ee 0.76 4.41523 4.3 5
目前仅能单独对某一列执行t检验:
# 单独计算aa列的t检验 res <- t.test(aa ~ Group, data = df) res
输出结果:
Welch Two Sample t-test data: aa by Group t = 0.41523, df = 11.794, p-value = 0.6854 alternative hypothesis: true difference in means between group High and group Low is not equal to 0 95 percent confidence interval: -2.660919 3.910919 sample estimates: mean in group High mean in group Low 6.125 5.500
解决方案
方法一:Base R循环实现
遍历需要分析的列,逐个执行t检验,提取所需统计量并整理成结果数据框:
# 定义需要分析的列(排除Group列) cols <- setdiff(names(df), "Group") # 初始化结果列表 result_list <- lapply(cols, function(col) { # 执行t检验 test_res <- t.test(reformulate("Group", response = col), data = df) # 提取所需统计量 data.frame( values = col, pvalue = round(test_res$p.value, 3), t = round(test_res$statistic, 5), mean_in_High = round(test_res$estimate[1], 1), mean_in_Low = round(test_res$estimate[2], 1) ) }) # 合并列表为数据框 final_result <- do.call(rbind, result_list) # 重命名列名匹配预期格式 colnames(final_result) <- c("values", "pvalue", "t", "mean in High", "mean in Low") print(final_result)
运行后输出:
values pvalue t mean in High mean in Low 1 aa 0.685 0.41523 6.1 5.5 2 bb 0.890 0.13981 7.1 6.9 3 cc 0.088 1.80467 5.0 3.5 4 dd 0.121 -1.65972 7.4 5.9 5 ee 0.760 -0.31068 4.7 5.1
方法二:使用tidyverse + broom包简化流程
借助dplyr的分组和broom的tidy()函数,可以更简洁地整理统计结果:
首先安装并加载所需包:
install.packages(c("tidyverse", "broom")) library(tidyverse) library(broom)
然后执行以下代码:
final_result <- df %>% # 将数据转换为长格式 pivot_longer(cols = -Group, names_to = "values", values_to = "value") %>% # 按变量分组 group_by(values) %>% # 执行t检验并整理结果 summarise( t_test = list(t.test(value ~ Group)), .groups = "drop" ) %>% # 提取t检验的统计量 mutate( tidied = map(t_test, tidy), means = map(t_test, ~ .x$estimate) ) %>% # 展开统计量列 unnest(tidied) %>% # 提取两组均值 mutate( `mean in High` = round(map_dbl(means, 1), 1), `mean in Low` = round(map_dbl(means, 2), 1) ) %>% # 选择并重命名所需列 select(values, pvalue = p.value, t = statistic, `mean in High`, `mean in Low`) %>% # 保留小数位数匹配需求 mutate( pvalue = round(pvalue, 3), t = round(t, 5) ) print(final_result)
得到的结果与Base R方法一致,代码更具可读性。
内容的提问来源于stack exchange,提问作者user2110417
相关产品推荐
相关产品推荐

