91

2019 年编辑: 此问题是data.table在 2016 年 11 月更改之前提出的,请参阅下面接受的当前和以前方法的答案。

我有一个data.table大约 250 万行的表。有两列。我想删除在两列中重复的任何行。以前对于data.frame,我会这样做: df -> unique(df[,c('V1', 'V2')])但这不适用于data.table。我已经尝试过unique(df[,c(V1,V2), with=FALSE]),但它似乎仍然只对 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")
4

5 回答 5

111

对于 v1.9.8+2016 年 11 月发布

From?unique.data.table 默认使用所有列(与 一致?unique.data.frame

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

或者使用by参数来获得特定列的唯一组合(就像以前使用的键一样)

unique(dt, by = "V2")
   V1 V2
1:  A  B
2:  A  C
3:  A  D
4:  B  A
5:  E  F
6:  G  G

之前的 v1.9.8

?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

于 2012-08-03T09:04:08.657 回答
9

使用您的示例 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

因此,您可以列出表的列,然后获取其中的列,而无需按照@Andrie 的解决方案的要求(并由@MatthewDowle 编辑)unique()将键设置为所有列或将其删除(通过将其设置为) 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
于 2013-01-16T02:50:43.143 回答
1

unique(df)适用于您的示例。

于 2012-08-03T09:03:29.623 回答
1

这应该适合你

dt <- unique(dt, by = c('V1', 'V2'))
于 2019-04-08T10:21:01.197 回答
0

保留 data.table 表示法,您可以使用:

unique(df[, .(V1, V2, V3), nomatch=0 ])

如这里https://stackoverflow.com/a/31875208/10087503

我没有比较这个和 Magma 版本的速度。

于 2020-05-20T09:54:41.733 回答