用重复的列名绑定两个数据框的行(通过列名合并)。

4
我希望能够通过列名将两个数据框的行绑定在一起,如果第二个数据框中不存在该列,则第一个数据框应有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

What I'd like to get?

   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

提前感谢您的帮助!

2个回答

3
使用data.table中的rbindlist选项
使用data.table中的rbindlist选项可以很方便地将多个数据表按行合并为一个数据表。
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

是的,它运行得很好,谢谢。然而,当我处理更大的数据时,出现了“错误:内存耗尽(达到限制?)”,因此我必须找到其他解决方案。 - Adamm

2
另一个选择可能是将数据框转换为列表对象,然后使用rowr包中的cbind.fill函数进行cbind操作,其中fill = NA。"Original Answer"翻译成“最初的回答”。
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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接