2015-10-24 42 views
0

我想改進我的一段代碼。假設您要刪除具有相同「標籤」和「ID」的重複行。我這樣做的方式是:data.table:刪除給定索引值的行的重複子集

library(data.table) 
dt <- data.table(label = c("A", "A", "B", "B", "C", "A", "A", "A"), 
       id = c(1, 1, 2, 2, 3, 4, 5, 5)) 
tmp = dt[label == 'A',] 
tmp = unique(tmp, by = 'id') 
dt = dt[label != 'A',] 
dt = rbind(dt, tmp) 

有沒有更聰明/更短的方式來實現它?如果可能通過參考? 此代碼看起來非常難看,並且意味着很多副本。

(而且我有幾個標籤當前操作,但不是所有的人。因此,這意味着4號線爲每一個標籤...)

謝謝!

實施例:

label id 
A  1 
A  1 
B  2 
B  2 
C  3 
A  4 
A  5 
A  5 

會得到:

label id 
A  1 
B  2 
B  2 
C  3 
A  4 
A  5 

注意,線3和4的停留複製,因爲該標籤是等於 'B' 而不是 'A'。

+1

因爲它應有一個也做了一些重複的行是相關的,但其他一些則不是。所以我想根據他們的標籤去除其中的一部分。 –

回答

3

沒有必要再創建tmp然後rbind它。如果你想這樣做了幾個標籤

dt[label != "A" | !duplicated(dt, by=c("label", "id"))] 
# label id 
# 1:  A 1 
# 2:  B 2 
# 3:  B 2 
# 4:  C 3 
# 5:  A 4 
# 6:  A 5 

:您可以簡單地使用duplicated功能如下

dt[!label %in% c("A", "C") | !duplicated(dt, by=c("label", "id"))] 

?duplicated瞭解更多關於重複數據刪除功能data.table。 p 它是什麼我工作的目的:

+0

好的一段代碼!有用。謝謝 –

+2

雙重負面的東西讓我很失望。對於類似的情況:'dt [!(label ==「A」&duplicated(dt,by = c(「label」,「id」)))]' – Frank

1

這個目標可以使用if/else條件

dt[, if(all(label=='A')) .SD[1L] else .SD, by = id] 
# id label 
#1: 1  A 
#2: 2  B 
#3: 2  B 
#4: 3  C 
#5: 4  A 
#6: 5  A