R 查找数据帧的补码(反连接)
我有两个数据帧(df和df1)。df1是df的子集。我想得到一个数据帧,它是df中df1的补充,即返回第一个数据集中第二个数据集中不匹配的行。比如说, 数据帧df: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[!
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)
sqlsetdiff
和%
中的%几乎是同一个函数。@Davidernburg-同意,这就是为什么我认为这只是一个易读性和品味的问题。@Davidernburg,该函数是match
@MaratTalipov我知道,这就是我对base R解决方案的建议投票,虽然它可能不是这里最快的一个。如果我想进行反连接并具有多个键/列,语法是什么样子的?@Blind0ne:您可以使用交互
或粘贴
对多个键进行反连接<代码>键我喜欢在设置键后使用merge[df,df2]。这个操作的反义词是什么?@hermantoothot答案实际上是df[!df2]
,这与您所写的相反。如果on
中的键有不同的名称会怎么样?@JdeMello您可以指定不同的键-请参见?数据。表在“参数”部分查找on
。AFAIKfsetdiff(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)