R 查找数据帧的补码(反连接)

R 查找数据帧的补码(反连接),r,join,merge,r-faq,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 从dplyr library(dplyr) anti_join(df, df1, by='heads') 尝试%中的%命令,并使用将其反转 df[!

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

数据帧df:

heads
row1
row2
row3
row4
row5
数据帧df1:

heads
row3
row5
然后,期望输出df2为:

heads
row1
row2
row4

dplyr

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

尝试%中的
%命令,并使用
将其反转

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

您还可以使用
data.table
s二进制联接执行某种类型的反联接

library(data.table)
setkey(setDT(df), heads)[!df1]
#    heads
# 1:  row1
# 2:  row2
# 3:  row4

编辑:启动data.table v1.9.6+我们可以在使用
on

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)

另一个选项,使用base R和
setdiff
功能:

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

df2通过操作
plyr
软件包的
match\u df
代码,创建函数
negative\u match\u df
的另一个选项

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]
}

dplyr还有
setdiff()
,它将为您提供

setdiff(bigFrame,smallFrame)
获取第一个表中的额外记录

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


dplyr有很多很好的功能:有关快速简单的指南,请参见“迟来的答案”,但对于另一个选项,我们可以尝试使用
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
setdiff
和%
中的
%几乎是同一个函数。@Davidernburg-同意,这就是为什么我认为这只是一个易读性和品味的问题。@Davidernburg,该函数是
match
@MaratTalipov我知道,这就是我对base R解决方案的建议投票,虽然它可能不是这里最快的一个。如果我想进行反连接并具有多个键/列,语法是什么样子的?@Blind0ne:您可以使用
交互
粘贴
对多个键进行反连接<代码>键我喜欢在设置键后使用merge[df,df2]。这个操作的反义词是什么?@hermantoothot答案实际上是
df[!df2]
,这与您所写的相反。如果
on
中的键有不同的名称会怎么样?@JdeMello您可以指定不同的键-请参见
?数据。表
在“参数”部分查找
on
。AFAIK
fsetdiff(all=T)
不会有帮助,它会将整行视为元素,并减去重复行的数量。X=1,1,1,1;Y=1,1;然后它给出两行,因为4-2=2。Antijoin将给出0。它是否像anti join那样处理重复?在中,setdiff说,管理重复。我打开链接,看到“小心intersect()、union()和setdiff()删除重复项”anti join保留LHS上的重复行,忽略RHS上的重复行。行是指我们连接的列。另一方面,data.table setops管理重复项,但它仍然不是反连接,
negate_match_df(df,df1)
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)