【问题标题】:Binding rows of two data frames (merging by column names) with duplicated column names将两个数据框的行(按列名合并)与重复的列名绑定
【发布时间】:2019-02-07 09:04:21
【问题描述】:

我想通过列名绑定两个 df 的行,如果第二个 df 中不存在列,首先应该有 NA。不幸的是dplyr::bind_rows 有重复列名的问题。你能帮我解决这个问题吗?

到目前为止我做了什么?

首先是一些可重现的数据:

df1 <- data.frame(replicate(6,sample(0:1,10,rep=TRUE)))
df2 <- data.frame(replicate(3,sample(0:1,10,rep=TRUE)))
colnames(df1) <- c('A','A','A','B','C','E')
colnames(df2) <- c('A','B','C')

df1
   A A A B C E
1  0 1 0 1 1 1
2  1 1 1 0 0 0
3  0 0 1 1 0 1
4  0 0 1 0 1 1
5  0 1 0 1 1 0
6  1 0 1 1 1 1
7  0 0 1 1 1 0
8  0 1 0 1 1 0
9  0 1 0 0 1 0
10 1 1 0 1 1 0

df2
   A B C
1  1 1 0
2  0 1 1
3  1 1 0
4  1 0 0
5  0 0 1
6  0 0 1
7  0 1 1
8  0 0 0
9  0 0 1
10 0 1 1

我想要什么?

   A A A B C E
1  0 1 0 1 1 1
2  1 1 1 0 0 0
3  0 0 1 1 0 1
4  0 0 1 0 1 1
5  0 1 0 1 1 0
6  1 0 1 1 1 1
7  0 0 1 1 1 0
8  0 1 0 1 1 0
9  0 1 0 0 1 0
10 1 1 0 1 1 0
11 1 1 1 1 0 NA
12 0 0 0 1 1 NA
13 1 1 1 1 0 NA
14 1 1 1 0 0 NA
15 0 0 0 0 1 NA
16 0 0 0 0 1 NA
17 0 0 0 1 1 NA
18 0 0 0 0 0 NA
19 0 0 0 0 1 NA
20 0 0 0 1 1 NA

我决定从dplyr 使用bind_rows,但是:

result <- bind_rows(mutate_all(df1, as.character), mutate_all(df2, as.character))
Error: Columns `A`, `A` must have unique names
Call `rlang::last_error()` to see a backtrace

提前感谢您的帮助!

【问题讨论】:

    标签: r dataframe merge


    【解决方案1】:

    使用来自data.tablerbindlist 的选项

    library(data.table)
    cols <- names(df1)[names(df1) %in% names(df2)]
    out <- setDF(rbindlist(list(df1, setNames(df2[cols], cols)), fill = TRUE))
    out
    #   A A A B C  E
    #1  0 1 0 1 1  0
    #2  1 1 1 0 1  0
    #3  0 1 1 0 1  0
    #4  0 0 1 0 1  0
    #5  1 0 0 1 0  1
    #6  1 1 1 1 0  1
    #7  0 0 0 1 0  0
    #8  0 0 0 1 0  0
    #9  1 1 0 1 0  0
    #10 0 1 0 1 1  0
    #11 0 0 0 1 1 NA
    #12 1 1 1 1 0 NA
    #13 0 0 0 0 1 NA
    #14 0 0 0 0 1 NA
    #15 0 0 0 0 1 NA
    #16 1 1 1 1 1 NA
    #17 0 0 0 0 0 NA
    #18 1 1 1 1 1 NA
    #19 0 0 0 1 0 NA
    #20 0 0 0 1 1 NA
    

    df2[cols] 部分将产生以下具有唯一名称的数据框

    #   A A.1 A.2 B C
    #1  0   0   0 1 1
    #2  1   1   1 1 0
    #3  0   0   0 0 1
    # ...
    

    这就是为什么我们调用setNames(df2[cols], cols) 来立即重命名列。 setDF 确保结果是 data.frame 而不是 data.table


    使用 bind_rows 你最终只会得到四列

    head(bind_rows(df1, setNames(df2[cols], cols)), 3)
    #  A B C E
    #1 1 1 0 0
    #2 0 0 0 0
    #3 0 0 1 1
    

    【讨论】:

    • 是的,效果很好,谢谢。不过,有了更大的数据,我得到了Error: memory exhausted (limit reached?),所以我必须找到其他解决方案。
    【解决方案2】:

    另一种选择是将数据框转换为列表对象,然后使用 cbind.fill 来自 rowr 包和 fill = NAcbind 将它们转换为 fill = NA

    library(rowr)
    
    new_df <- do.call(cbind.fill, c(mapply(c, as.list(df1),
             as.list(df2)[match(names(df1), names(df2))]), fill = NA))
    

    但这会丢失列名,您可以从 df1 将其返回。

    names(new_df) <-  names(df1)
    new_df
    
    #   A A A B C  E
    #1  0 1 0 0 1  0
    #2  0 1 0 0 0  0
    #3  0 0 1 1 1  1
    #4  0 0 1 0 1  0
    #5  1 0 0 0 0  0
    #6  0 0 1 0 1  1
    #7  0 1 0 0 1  0
    #8  0 1 0 0 0  0
    #9  0 1 1 0 1  1
    #10 1 1 1 0 1  1
    #11 0 0 0 1 0 NA
    #12 1 1 1 0 0 NA
    #13 1 1 1 1 0 NA
    #14 0 0 0 1 0 NA
    #15 0 0 0 1 1 NA
    #16 1 1 1 1 0 NA
    #17 0 0 0 1 1 NA
    #18 1 1 1 0 0 NA
    #19 1 1 1 0 1 NA
    #20 1 1 1 0 1 NA
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-27
      • 1970-01-01
      • 1970-01-01
      • 2017-10-31
      • 1970-01-01
      • 1970-01-01
      • 2021-12-28
      • 1970-01-01
      相关资源
      最近更新 更多