将数据帧组合在两个不同的列表中,这些列表以 R 中的元素名称为键

Combine dataframes in two different lists keyed on the element name in R

我有两个列表 list1list2,每个列表都包含由名称唯一标识的数据框或数据表。我想将 list1list2 键合到数据集的名称上。我希望两个列表的元素都出现在组合列表中。我已经尝试了很多来自 Whosebug 的解决方案,例如 do.call(c, list1, list2)Map(c, list1, list2)mapplymergelist.join。我获得的最大成功是通过创建数据框名称的键并将 Map 与键一起使用,但它们没有在组合列表中保留不匹配的元素,例如 keys <- unique(c(names(list1), names(list2))combined_list <- Map(rbind, list1[keys], list2[keys])。但是 none 他们以我想要的方式为我工作。

基本上我想对两个列表中包含的同名数据集执行rbind。这些列表的长度可能不同,并且包含不同的元素,有时还会有重叠的元素。

list1list2 的样子:

a <- data.frame(id = 1:5, type =c("a", "b", "c", "d", "e"))
b <- data.frame(id = 6:10, type =c("f", "g", "h", "i", "j"))
c <- data.frame(id = 11:15, type =c("k", "l", "m", "n", "o"))

list1 <- list(a=a,b=b,c=c)

a <- data.frame(id = 16:20, type =c("p", "q", "r", "s", "t"))
b <- data.frame(id = 21:25, type =c("u", "v", "w", "x", "y"))
e <- data.frame(id = 26:30, type =c("z", "ab", "ac", "ad", "ae"))
f <- data.frame(id = 31:35, type =c("ba", "bb", "bc", "bd", "be"))

list2 <- list(a=a,b=b,e=e, f=f)

预期的结果应该是这样的:

a <- data.frame(id = c(1:5, 16:20), type =c("a", "b", "c", "d", "e", "p", "q", "r", "s", "t"))
b <- data.frame(id = c(6:10,21:25), type =c("f", "g", "h", "i", "j", "u", "v", "w", "x", "y"))
c <- data.frame(id = 11:15, type =c("k", "l", "m", "n", "o"))
e <- data.frame(id = 26:30, type =c("z", "ab", "ac", "ad", "ae"))
f <- data.frame(id = 31:35, type =c("ba", "bb", "bc", "bd", "be"))

combined_list <- list(a=a, b=b, c=c, e=e, f=f)

非常感谢在这方面的任何回应。 P.S。这是我在 SO 上的第一个 post。 :)

您可以尝试使用 list1list2 中的 unique names,因为您已经尝试过,然后将它们用于 setnames:

keys <- unique(c(names(list1), names(list2)))
x <- setNames(Map(rbind, list1[keys], list2[keys]), keys)
identical(x, combined_list)
#[1] TRUE

或使用 lapply:

x <- lapply(setNames(keys, keys), function(x) {rbind(list1[[x]], list2[[x]])})
identical(x, combined_list)
#[1] TRUE

对于任意数量的data.frames列表,这也可以用splitrbind来完成:

ll <- do.call('c', list(list1, list2))
lapply(split(ll, names(ll)), function(x){
    do.call('rbind', args = c(x, list(make.row.names = F)))
})

# $a
#    id type
# 1   1    a
# 2   2    b
# 3   3    c
# 4   4    d
# 5   5    e
# 6  16    p
# 7  17    q
# 8  18    r
# 9  19    s
# 10 20    t
# 
# $b
#    id type
# 1   6    f
# 2   7    g
# 3   8    h
# 4   9    i
# 5  10    j
# 6  21    u
# 7  22    v
# 8  23    w
# 9  24    x
# 10 25    y
# 
# $c
#   id type
# 1 11    k
# 2 12    l
# 3 13    m
# 4 14    n
# 5 15    o
# 
# $e
#   id type
# 1 26    z
# 2 27   ab
# 3 28   ac
# 4 29   ad
# 5 30   ae
# 
# $f
#   id type
# 1 31   ba
# 2 32   bb
# 3 33   bc
# 4 34   bd
# 5 35   be

如果我正确理解你的问题,一个选项是将两个列表放在一个数据中。frame/tibble然后按组拆分为列表项:

library(purrr)
library(dplyr)

df_of_lists <- dplyr::union(list1 %>% 
                              purrr::map_df(as.data.frame, .id = 'name'),
                            list2 %>% 
                              purrr::map_df(as.data.frame, .id = 'name'))

split(df_of_lists, f = df_of_lists$name ) %>%
# in case you want to remove the new name colum
purrr::map( ~ .x %>% dplyr::select(-name))