在R中计算多个数据框列表间的元素级中位数
问题描述
我有多个列表,每个列表里包含多个data frame,想要计算各列表内对应位置data frame的元素级中位数——也就是取list1[[1]][1,1]、list2[[1]][1,1]、list3[[1]][1,1]的中位数,以此类推覆盖所有元素。以下是仅含两列的示例数据:
set.seed(1) list1 <- list(data.frame(a = sample.int(10, 4), b = sample.int(10, 4)), data.frame(a = sample.int(10, 4), b = sample.int(10, 4))) list2 <- list(data.frame(a = sample.int(10, 4), b = sample.int(10, 4)), data.frame(a = sample.int(10, 4), b = sample.int(10, 4))) list3 <- list(data.frame(a = sample.int(10, 4), b = sample.int(10, 4)), data.frame(a = sample.int(10, 4), b = sample.int(10, 4)))
预期输出结果:
[[1]] a b 7 4 9 9 7 3 4 6 [[2]] a b 5 7 8 6 2 6 5 2
解决方法
方法一:Base R原生实现
核心逻辑是先把所有列表中对应位置的data frame归为一组,再对每组的元素维度计算中位数:
# 将所有目标列表合并为一个大列表 all_lists <- list(list1, list2, list3) # 对每个位置的data frame组,逐元素计算中位数 result <- Map(function(...) { # 把当前组的data frame转换为三维数组,方便按元素位置聚合 arr <- array(unlist(list(...)), dim = c(nrow(list(...)[[1]]), ncol(list(...)[[1]]), length(list(...)))) # 对每个(row, col)位置计算中位数,再转回data frame格式 as.data.frame(apply(arr, c(1,2), median)) }, all_lists[[1]], all_lists[[2]], all_lists[[3]])
方法二:Tidyverse工具链实现
如果习惯tidyverse风格,可以用purrr做分组映射,结合dplyr做聚合计算:
library(purrr) library(dplyr) # 把三个列表中对应位置的data frame配对成组 paired_dfs <- pmap(list(list1, list2, list3), list) # 对每组data frame计算元素级中位数 result <- map(paired_dfs, function(dfs) { # 给每个data frame添加行索引,确保按位置聚合 indexed_dfs <- map(dfs, ~ mutate(.x, row_idx = row_number())) # 合并所有data frame,按行分组后计算每列的中位数 bind_rows(indexed_dfs) %>% group_by(row_idx) %>% summarise_all(median) %>% select(-row_idx) %>% as.data.frame() })
运行上述任意一种方法,都能得到符合预期的元素级中位数结果。
内容的提问来源于stack exchange,提问作者asm
相关产品推荐
相关产品推荐

