基于tidyverse的统计分析与数据合并代码优化问询
简化分组统计与威尔科克森检验的代码实现
数据集
首先加载所需包并导入数据集:
library(tidyverse) df <- structure(list(L1 = c("Age Class", "Age Class", "Age Class", "Age Class", "Gender", "Gender", "Gender", "Age Class", "Age Class", "Age Class", "Gender", "Gender", "Age Class", "Age Class", "Age Class", "Gender"), L2 = c("Older Youth", "Older Youth", "Younger Youth", "Younger Youth", "Female", "Female", "Female", "Younger Youth", "Older Youth", "Older Youth", "Male", "Male", "Younger Youth", "Older Youth", "Older Youth", "Female"), scr = c(0.78125, 0.90625, 0.90625, 0.6875, 0.875, 0.78125, 1, 0.65625, 0.75, 0.59375, 0.8125, 0.75, 0.65625, 0.6875, 0.75, 0.75)), row.names = c(NA, -16L), class = "data.frame")
需求回顾
需要完成以下操作:
- 计算整体数据的中位数(median)和标准误(standard error)
- 按
L1和L2分组计算中位数和标准误 - 在
L1组内针对两个L2水平执行威尔科克森检验(wilcoxon test) - 合并前两步的统计结果,再与检验的p值关联得到最终输出
简化代码方案
方案1:嵌套数据框+链式操作
这种写法符合tidy数据理念,避免多层列表嵌套,逻辑清晰:
final_result <- df %>% # 复制一份数据标记为整体分组,统一后续统计 bind_rows(mutate(., L1 = "All", L2 = "All")) %>% # 计算所有分组的中位数和标准误 summarise( mdn = median(scr), se = sd(scr)/sqrt(n()), .by = c(L1, L2) ) %>% # 关联威尔科克森检验的p值 left_join( df %>% # 按L1分组嵌套数据 nest(data = -L1) %>% # 对每个L1组执行检验并提取p值 mutate(pv = map_dbl(data, ~wilcox.test(scr ~ L2, data = .x)$p.value)) %>% select(L1, pv) %>% # 给整体分组添加NA的p值(无L2对比) add_row(L1 = "All", pv = NA_real_), by = "L1" ) print(final_result)
方案2:紧凑链式写法
如果偏好更简洁的代码结构,可以直接合并整体与分组统计后关联检验结果:
final_result <- df %>% { bind_rows( # 单独计算整体统计 mutate(., L1 = "All", L2 = "All") %>% summarise(mdn = median(scr), se = sd(scr)/sqrt(n()), .by = c(L1, L2)), # 计算分组统计 summarise(., mdn = median(scr), se = sd(scr)/sqrt(n()), .by = c(L1, L2)) ) } %>% left_join( df %>% summarise(pv = wilcox.test(scr ~ L2)$p.value, .by = L1) %>% add_row(L1 = "All", pv = NA_real_), by = "L1" ) print(final_result)
代码说明
- 两种方案都摒弃了原代码的多层列表处理,用tidyverse原生函数完成合并与统计
- 嵌套数据框的写法(方案1)扩展性更强,后续新增分组检验逻辑更方便
- 整体分组的p值设为
NA,符合“无L2水平对比则无检验结果”的逻辑
内容的提问来源于stack exchange,提问作者Salty
相关产品推荐
相关产品推荐

