【问题标题】:Combine dataframes in two different lists keyed on the element name in R将数据框组合在两个不同的列表中,以 R 中的元素名称为键
【发布时间】:2021-02-17 02:34:06
【问题描述】:

我有两个列表list1list2,每个列表都包含由其名称唯一标识的数据框或数据表。我想结合list1list2 键入数据集的名称。我希望两个列表的元素都出现在组合列表中。我已经尝试了很多来自 stackoverflow 的解决方案,例如 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])。但它们都没有按我想要的方式为我工作。

基本上,我想对两个列表中包含的同名数据集执行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)

非常感谢您在这方面的任何回复。 附:这是我关于 SO 的第一篇文章。 :)

【问题讨论】:

    标签: r list merge concat


    【解决方案1】:

    您可以尝试使用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
    

    【讨论】:

    • 非常感谢。您使用 setNames 的解决方案就像一个奇迹。
    【解决方案2】:

    如果我正确理解了您的问题,一个选项是在一个 data.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))
    

    【讨论】:

      【解决方案3】:

      对于任意数量的 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
      

      【讨论】:

      • 这个解决方案的工作原理类似于上面的 setNames 函数。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-21
      • 1970-01-01
      • 2023-01-28
      • 2015-04-22
      • 2019-01-31
      • 2023-02-23
      • 2021-01-24
      相关资源
      最近更新 更多