查找数据框的补充(反连接)

时间:2015-02-24 17:59:45

标签: r join merge r-faq

我有两个数据帧(df和df1)。 df1是df的子集。我想得到一个数据帧,它是df中df1的补码,即返回第二个数据集中不匹配的第一个数据集。例如,让,

数据框df:

heads
row1
row2
row3
row4
row5

数据框df1:

heads
row3
row5

然后所需的输出df2为:

heads
row1
row2
row4

7 个答案:

答案 0 :(得分:52)

您还可以使用data.table二进制连接

进行某种类型的反连接
library(data.table)
setkey(setDT(df), heads)[!df1]
#    heads
# 1:  row1
# 2:  row2
# 3:  row4

编辑:启动data.table v1.9.6 + 我们可以在使用on时无需设置密钥即可加入data.tables

setDT(df)[!df1, on = "heads"]

EDIT2:引入了data.table v1.9.8 + fsetdiff,它基本上是上述解决方案的一种变体,只是在所有列名称上例如,x data.table x[!y, on = names(x)]。如果all设置为FALSE(默认行为),则只会返回x中的唯一行。对于每个data.table中只有一列的情况,以下内容将等同于之前的解决方案

fsetdiff(df, df1, all = TRUE)

答案 1 :(得分:25)

anti_join

尝试dplyr
library(dplyr)
anti_join(df, df1, by='heads')

答案 2 :(得分:19)

尝试使用%in%命令并将其反转为!

df[!df$heads %in% df1$heads,]

答案 3 :(得分:6)

另一种选择,使用基数R和setdiff函数:

df2 <- data.frame(heads = setdiff(df$heads, df1$heads))

setdiff完全按照您的想象运作;将两个参数作为集合,并从第一个中删除第二个中的所有项目。

我发现setdiff更具可读性%in%并且在我不需要时更不需要额外的库,但您使用的答案主要是个人品味问题。

答案 4 :(得分:5)

dplyr也有setdiff(),它会为你提供

enter image description here

setdiff(bigFrame, smallFrame)会在第一个表格中为您提供额外的记录。

因此,对于OP的示例,代码将显示为setdiff(df, df1)

dplyr有很多很棒的功能:快速简单的指南请参阅here.

答案 5 :(得分:1)

通过操纵negate_match_df match_df个软件包的代码来创建函数plyr的另一个选项。

library(plyr)
negate_match_df <- function (x, y, on = NULL) 
{
if (is.null(on)) {
    on <- intersect(names(x), names(y))
    message("Matching on: ", paste(on, collapse = ", "))
}
keys <- join.keys(x, y, on)
x[!keys$x %in% keys$y, , drop = FALSE]
}

数据

df <- read.table(text ="heads
row1
row2
row3
row4
row5",header=TRUE)

df1 <- read.table(text ="heads
row3
row5",header=TRUE)

<强>输出

negate_match_df(df,df1)

答案 6 :(得分:1)

最新答案,但是对于另一种选择,我们可以尝试使用sqldf软件包进行正式的SQL反连接:

library(sqldf)
sql <- "SELECT t1.heads
        FROM df t1 LEFT JOIN df1 t2
            ON t1.heads = t2.heads
        WHERE t2.heads IS NULL"
df2 <- sqldf(sql)

sqldf软件包对于那些使用SQL逻辑很容易表达的问题,但对于使用base R或另一个R软件包却不太容易表达的问题很有用。