2015-09-24 108 views
0

对于两个数据帧df.1df.2,我想知道df.1中不在df.2的行,即已消失或更改的行。 这里是例子:setdiff of row in R

df.1 = cbind.data.frame(a = 1:4, b = 2:5, c = 99:102) 
> df.1 
    a b c 
1 1 2 99 
2 2 3 100 
3 3 4 101 
4 4 5 102 

df.2 = cbind.data.frame(a = c(1:3,7), b = c(3,3:4,9), c=c(99:100, 102, 105)) 
> df.2 
    a b c 
1 1 3 99 
2 2 3 100 
3 3 4 102 
4 7 9 105 

所以在这里我需要的输出是行1,3和4 df.1

> desired.output 
    a b c 
1 1 2 99 
3 3 4 101 
4 4 5 102 

如果df.1df.2是矢量我可以用setdiff(df.1, df.2)但我不看到一个简单/优雅的方式将其应用于数据框。

有什么比这些解决方法我认为是更优雅:

  • 比较柱df.1df.2列,然后采取联合的所有列
  • 使得dataframes他们的所有行的列表,然后使用setdiff并转换回数据帧
+2

我觉得这是一个重大的欺骗。 Usualy最受欢迎的答案是'library(dplyr); anti_join(df.1,df.2)' –

回答

3

我认为,最优雅(语法糖和非常高效)使用data.table包:

library(data.table) 
setDT(df.1)[!df.2, on = names(df.1)] 
# a b c 
# 1: 1 2 99 
# 2: 3 4 101 
# 3: 4 5 102 

请注意,这是不同的:

setDT(df.2)[!df.1, on = names(df.2)] 
# a b c 
# 1: 1 3 99 
# 2: 3 4 102 
# 3: 7 9 105 
+0

也许只是'setDT(df.1)[!df.2,on = names(df.1)]'。你不需要再在V 1.9.6+中输入密码。你不需要他们都是'data.table' –

+0

@DavidArenburg有趣。我会更新我的答案。 – agstudy

+0

@DavidArenburg这意味着一个表(键)不需要是data.table在这里! – agstudy

4

这是方便dplyr使用anti_join。

library(dplyr) 
anti_join(df.1,df.2) 
Joining by: c("a", "b", "c") 
    a b c 
1 1 2 99 
2 4 5 102 
3 3 4 101 
+0

这需要'setDT',否则我会得到这样的错误:'data.table :: setkeyv(y,by $ x)中的错误:x不是data.table' – mts

+1

在干净的数据集上试一下(不是' data.table')。 –

+0

@DavidArenburg真实,它在一个干净的数据集上工作,谢谢! – mts

1

使用sqldf

library(sqldf) 
sqldf('SELECT * FROM [df.1] EXCEPT SELECT * FROM [df.2]') 

输出:

a b c 
1 1 2 99 
2 3 4 101 
3 4 5 102