2015-09-24 84 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