如何合并二级列表中同名data.frame为单个data.frame?
针对你拥有的二级列表结构(一级列表项均为包含同名data.frame的子列表),可以通过列表转置+批量合并的方式快速实现需求,以下是具体解法及对你尝试问题的说明:
核心解法:转置列表后批量合并
利用purrr::transpose()将原列表的层级转置,把所有同名的data.frame归为同一组,再用map()结合dplyr::bind_rows()合并每组数据:
library(purrr) library(dplyr) # 你的示例列表 MyList <- list("A" = list("apples" = data.frame(X = 1:5, Source = "A"), "mangoes" = data.frame(X = 1:5, Source = "A")), "B" = list("apples" = data.frame(X = 1:5, Source = "B"), "mangoes" = data.frame(X = 1:5, Source = "B")), "C" = list("apples" = data.frame(X = 1:5, Source = "C"), "mangoes" = data.frame(X = 1:5, Source = "C"))) # 一步完成转置+合并 MyNewList <- MyList %>% transpose() %>% map(bind_rows)
验证结果:MyNewList$apples会包含来自A、B、C的所有行,完全符合你的预期。
另一种实现:遍历水果名批量提取合并
如果你不想用转置,也可以先获取二级列表的名称,再逐个提取合并:
# 获取二级列表的名称(比如apples、mangoes) fruit_names <- names(MyList[[1]]) # 遍历每个水果名,从所有一级列表中提取对应data.frame并合并 MyNewList <- lapply(fruit_names, function(fruit) { map_dfr(MyList, pluck, fruit) }) %>% set_names(fruit_names)
你之前尝试的问题说明
pluck(MyList, 1:3, "apples")无效:pluck()的参数是层级索引,不支持同时传入多个同级索引(1:3),它只能单次提取单个路径的元素。正确做法是用map(MyList, pluck, "apples")获取所有apples的data.frame列表,再用bind_rows()合并。lapply(c("apples", "mangoes"), function(x) pluck(MyList, x))返回NULL:
原列表的一级元素是"A"、"B"、"C",不存在名为"apples"的一级元素,所以pluck(MyList, x)找不到对应内容,返回NULL。需要改为从每个一级子列表中提取x,即map(MyList, pluck, x)。map_depth(MyList, .depth=2, .f=bind_rows)不符合预期:map_depth(.depth=2)是对每个二级的单个data.frame应用bind_rows(),而bind_rows()处理单个data.frame时不会改变它,所以最终结果和原列表结构一致,没有实现跨一级列表的合并。
内容的提问来源于stack exchange,提问作者shirewoman2

