2012-08-03 54 views
55

我有一個data.table表,大約有250萬行。有兩列。我想刪除兩列中重複的行。以前對於data.frame我會這樣做: df -> unique(df[,c('V1', 'V2')])但這不適用於data.table。我試過unique(df[,c(V1,V2), with=FALSE]),但它似乎仍然只對data.table的鍵而不是整行進行操作。在data.table中過濾出重複/非唯一的行

有什麼建議嗎?

乾杯, 戴維

>dt 
     V1 V2 
[1,] A B 
[2,] A C 
[3,] A D 
[4,] A B 
[5,] B A 
[6,] C D 
[7,] C D 
[8,] E F 
[9,] G G 
[10,] A B 

在上述data.table其中V2是表密鑰,只有行4,7和10將被移除。

> dput(dt) 
structure(list(V1 = c("B", "A", "A", "A", "A", "A", "C", "C", 
"E", "G"), V2 = c("A", "B", "B", "B", "C", "D", "D", "D", "F", 
"G")), .Names = c("V1", "V2"), row.names = c(NA, -10L), class = c("data.table", 
"data.frame"), .internal.selfref = <pointer: 0x7fb4c4804578>, sorted = "V2") 
+0

沒有使用獨特的'dt [,.N,by =。(V1,V2)] [,1:2]' – Akki 2017-12-22 11:14:06

回答

61

?unique.data.table,顯然在數據表上調用unique只對密鑰有效。這意味着在撥打unique之前,您必須將鑰匙重置爲所有列。

library(data.table) 
dt <- data.table(
    V1=LETTERS[c(1,1,1,1,2,3,3,5,7,1)], 
    V2=LETTERS[c(2,3,4,2,1,4,4,6,7,2)] 
) 

調用unique有一列的關鍵:

setkey(dt, "V2") 
unique(dt) 
    V1 V2 
[1,] B A 
[2,] A B 
[3,] A C 
[4,] A D 
[5,] E F 
[6,] G G 

重置鍵,所有列,然後調用unique

setkey(dt) 
unique(dt) 
    V1 V2 
[1,] A B 
[2,] A C 
[3,] A D 
[4,] B A 
[5,] C D 
[6,] E F 
[7,] G G 

編輯從馬修:

或者,而不是設置的關鍵在於這可能需要一些時間許多行和許多列的大表中的所有列,拔出鑰匙達到相同的結果:

setkey(dt,NULL) 
unique(dt) 
    V1 V2 
1: A B 
2: A C 
3: A D 
4: B A 
5: C D 
6: E F 
7: G G 
+0

只有在沒有設置密鑰的情況下才有效。我會編輯上面的問題以說明問題。對不起 – 2012-08-03 09:12:44

+0

@DavyKavanagh編輯 – Andrie 2012-08-03 09:26:17

+0

非常好。謝謝! – 2012-08-03 09:30:44

1

unique(df)適用於您的示例。

5

你的榜樣data.table ...

> dt<-data.table(V1 = c("B", "A", "A", "A", "A", "A", "C", "C", "E", "G"), V2 = c("A", "B", "B", "B", "C", "D", "D", "D", "F", "G")) 
> setkey(dt,V2) 

考慮以下測試:

> haskey(dt) # obviously dt has a key, since we just set it 
[1] TRUE 

> haskey(dt[,list(V1,V2)]) # ... but this is treated like a "new" table, and does not have a key 
[1] FALSE 

> haskey(dt[,.SD]) # note that this still has a key 
[1] TRUE 

所以,你可以列出的表列,然後利用該unique(),而無需設置鍵到@Andrie的解決方案要求(並由@MatthewDowle編輯),將所有列或丟棄(通過將其設置爲NULL)。 @Pop和@Rahul建議的解決方案並不適合我。

請參閱下面的嘗試3,這與您的初次嘗試非常相似。你的例子不清楚,所以我不知道爲什麼它不起作用。此外,這是幾個月前,當你發佈的問題,所以data.table已更新?

> unique(dt) # Try 1: wrong answer (missing V1=C and V2=D) 
    V1 V2 
1: B A 
2: A B 
3: A C 
4: A D 
5: E F 
6: G G 

> dt[!duplicated(dt)] # Try 2: wrong answer (missing V1=C and V2=D) 
    V1 V2 
1: B A 
2: A B 
3: A C 
4: A D 
5: E F 
6: G G 

> unique(dt[,list(V1,V2)]) # Try 3: correct answer; does not require modifying key 
    V1 V2 
1: B A 
2: A B 
3: A C 
4: A D 
5: C D 
6: E F 
7: G G 

> setkey(dt,NULL) 
> unique(dt) # Try 4: correct answer; requires key to be removed 
    V1 V2 
1: B A 
2: A B 
3: A C 
4: A D 
5: C D 
6: E F 
7: G G 
+2

也許一個新的'唯一(...,use.key = FALSE)'參數會有所幫助;現提交[FR#2483](https://r-forge.r-project.org/tracker/index.php?func=detail&aid=2483&group_id=240&atid=978)。 – 2013-01-18 00:23:36

+0

嗨@MatthewDowle。是的,這將是一個很好的方便。我認爲你在FR中的評論也是正確的 - 如果密鑰是唯一的,那麼'use.key = FALSE'可以被忽略。 – dnlbrky 2013-01-18 14:12:00

+1

data.table 1.9.6(並且不懷疑早期版本)有選項'by =',它可以用來覆蓋密鑰。設置'by = NULL'「使用所有列,並且類似於data.frame方法。」 – JWilliman 2015-12-01 23:20:15