如何链式按名称合并列表中的data.table并解决pmap报错问题
合并列表中同名data.table的链式操作方案
问题背景
我有一个包含数量不定、存在同名项的data.table的列表,需要使用rbindlist(fill=TRUE)合并所有同名的data.table,缺失列填充为NA,最终返回带有原名称的data.table列表。
示例数据代码:
library(data.table) # 创建列表A A_1 <- data.table(A = 1:2,B = 2:3) A_2 <- data.table(C = 100:102,D = 300:302,E = 1:3) A <- list(AA = A_1,BB = A_2) # 创建列表B B_1 <- data.table(A = 2:4,B = 1:3,F = 4:6) B_2 <- data.table(C = 10:12,D = 20:22,G = 1:3,I = 10:12) B <- list(AA = B_1,BB = B_2) # 创建列表C C_1 <- data.table(I = 1:2,J = 3:4) C_2 <- data.table(C = 1:3,D = 4:6) C <- list(AA = C_1,BB = C_2) # 合并为总列表DT DT <- c(A,B,C)
非链式写法可实现需求:
library(purrr) pmap(.l = list(y = unique(names(DT))), .f = function(y) rbindlist(DT[names(DT) %in% y],fill = TRUE)) %>% set_names(unique(names(DT)))
但实际场景中,DT由其他函数生成,希望通过链式操作(%>%)直接传入处理,无需先创建DT变量。尝试的链式写法报错,提示存在未使用的函数元素,需了解报错原因及正确的链式实现方法。
报错原因
pmap的设计目标是处理多个并行输入列表,将对应位置的元素一起传递给函数。你尝试的写法中,把整个DT列表作为管道输入,同时在.l里传入了unique(names(.))这个名称列表,导致pmap错误地将DT的每个元素与名称列表的元素一一配对传递,完全偏离了按名称分组合并的逻辑,因此报错。
正确链式实现方案
最优方案是先按列表元素名称分组,再对每个分组执行合并操作,同时自动保留原名称。以下是两种简洁实现:
方案1:使用purrr包的链式写法
library(purrr) library(data.table) # 替代生成DT的函数,直接用DT作为示例输入 DT %>% split(names(.)) %>% map(~rbindlist(., fill = TRUE))
方案2:基础R链式写法(无需purrr)
library(data.table) DT %>% split(names(.)) %>% lapply(function(x) rbindlist(x, fill = TRUE))
逻辑解释
split(names(.)):将原列表按元素名称分组,生成新列表,每个子列表包含所有同名的data.tablemap()/lapply():遍历每个分组,用rbindlist(fill=TRUE)合并,分组名称会自动作为结果列表的元素名称,完全符合需求。
原写法的修正(不推荐)
如果一定要基于pmap调整,需要将DT作为环境变量传递,写法较为繁琐,仅作逻辑参考:
library(purrr) library(data.table) DT %>% { dt_obj <- . name_vec <- unique(names(dt_obj)) pmap(list(y = name_vec), function(y) rbindlist(dt_obj[names(dt_obj) == y], fill = TRUE)) %>% set_names(name_vec) }
内容的提问来源于stack exchange,提问作者Phil
相关产品推荐
相关产品推荐

