代码之家  ›  专栏  ›  技术社区  ›  Haakonkas

按列将列表中的多个数据帧合并到另一个数据帧

r
  •  0
  • Haakonkas  · 技术社区  · 7 年前

    在我的代码中,我使用了多个 left_join 要将单独的数据帧合并到我正在DPLYR链中处理的数据帧。我将要与另一个合并的数据帧导入到一个列表中,然后使用laply直接在该列表上执行一些操作,以准备合并它们。

    从现在起,我用 list2env(list, envir = .GlobalEnv) 从列表中创建单独的数据帧,然后使用 左连接 要按每个数据帧的唯一列分别合并每个数据帧,如下所示:

    测试数据:

    名单:

    structure(list(df2 = structure(list(x = structure(c(2L, 1L, 3L
    ), .Label = c("A", "B", "C"), class = "factor"), a = c(-0.331543943439452, 
    0.0588350184156617, 1.03657229544754)), .Names = c("x", "a"), row.names = c(NA, 
    -3L), class = "data.frame"), df3 = structure(list(z = structure(c(3L, 
    2L, 1L), .Label = c("K", "L", "M"), class = "factor"), b = c(-0.897094152848114, 
    0.97612075490695, 0.650264147064918)), .Names = c("z", "b"), row.names = c(NA, 
    -3L), class = "data.frame")), .Names = c("df2", "df3"))
    

    要创建单独的数据帧:

    list2env(testlist, envir = .GlobalEnv)
    

    数据帧:

    structure(list(x = structure(1:3, .Label = c("A", "B", "C"), class = "factor"), 
        y = 1:3, z = structure(1:3, .Label = c("K", "L", "M"), class = "factor")), .Names = c("x", 
    "y", "z"), row.names = c(NA, -3L), class = "data.frame")
    

    加入:

    library(dplyr)
    
    test_df %>%
        left_join(., df2, by = "x") %>%
        left_join(., df3, by = "z")
    

    (请注意,我的列表大约有8个数据帧,每个数据帧有2-3列。为了简单起见,此列表中只包含两个数据帧)

    所有数据帧都有各自的“按”列。 我想知道的是,如果有一种更简单的方法可以做到这一点,例如直接与整个列表合并,并自动检测哪些列相似,并由它们为每个数据帧合并,而不是执行左联接八次?

    编辑

    我按照@akrun的建议尝试运行以下代码:

    out <- test
    for(i in seq_along(table_list)) {
      nm1 <- intersect(names(out), names(table_list[[i]]))
      out <- merge(out, table_list[[i]], by = nm1)
    }
    out
    

    在哪里? test 是要合并到的数据帧,并且 table_list 是数据帧列表。 这适用于这些小的测试数据帧,但似乎引入了数据帧中单个行的重复,从而导致更多的行。

    更复杂的示例数据框:

    structure(list(x = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L
    ), .Label = c("A", "B", "C", "D"), class = "factor"), y = c(1, 
    2, 3, 4, 1, 2, 3, 4), z = structure(c(1L, 2L, 3L, 1L, 2L, 3L, 
    1L, 2L), .Label = c("K", "L", "M"), class = "factor")), .Names = c("x", 
    "y", "z"), row.names = c(NA, -8L), class = "data.frame")
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   phiver    7 年前

    使用复杂的测试,为什么不使用 reduce purrr 和左派一起加入DPLYR?我在下面的代码中包含了这些消息和警告消息。

    library(dplyr)
    library(purrr)
    
    all_dfs <- reduce(my_list, left_join, .init = test_df)
    
    # (warning) messages from using left_join
    # Joining, by = "x"
    # Joining, by = "z"
    # Warning message:
    # Column `x` joining factors with different levels, coercing to character vector 
    
    all_dfs
    
      x y z           a          b
    1 A 1 K  0.05883502  0.6502641
    2 B 2 L -0.33154394  0.9761208
    3 C 3 M  1.03657230 -0.8970942
    4 D 4 K          NA  0.6502641
    5 A 1 L  0.05883502  0.9761208
    6 B 2 M -0.33154394 -0.8970942
    7 C 3 K  1.03657230  0.6502641
    8 D 4 L          NA  0.9761208
    
        2
  •  1
  •   akrun    7 年前

    根据描述,我们似乎需要在每个列之前检查相交的列名称 merge

    out <- test_df
    for(i in seq_along(testlist)) {
       nm1 <- intersect(names(test_df), names(testlist[[i]]))
       out <- merge(out, testlist[[i]], by = nm1, all.x = TRUE)
     }
    
    out
    #  z x y           a          b
    #1 K A 1  0.05883502  0.6502641
    #2 L B 2 -0.33154394  0.9761208
    #3 M C 3  1.03657230 -0.8970942