R 筛选出data.table中重复/非唯一的行

R 筛选出data.table中重复/非唯一的行,r,duplicates,data.table,R,Duplicates,Data.table,编辑2019年:该问题是在数据发生变化之前提出的。表于2016年11月,关于当前和以前的方法,请参见下面接受的答案 我有一个data.tabletable,大约有250万行。有两列。我想删除两列中重复的所有行。以前对于data.frame,我会这样做: df->unique(df[,c('V1','V2'))但这不适用于data.table。我尝试了unique(df[,c(V1,V2),with=FALSE]),但它似乎仍然只对data.table的键进行操作,而不是对整行进行操作 有什么建议

编辑2019年:该问题是在
数据发生变化之前提出的。表
于2016年11月,关于当前和以前的方法,请参见下面接受的答案

我有一个
data.table
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")
>dput(dt)
结构(列表)(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=,sorted=“V2”)

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

适用于v1.9.8+()

来自
?唯一的.data.table
默认情况下,将使用所有列(这与
?unique.data.frame
一致)

或者使用
by
参数来获得特定列的唯一组合(与之前使用的键相同)

上一版本1.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)]
)


使用您的示例数据。表

> 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)
因此,您可以列出表中的列,然后获取该列的
unique()
,而无需根据@Andrie(由@MatthewDowle编辑)的解决方案的要求,将键设置为所有列或将其删除(通过将其设置为
NULL
)。由@Pop和@Rahul提出的解决方案对我不起作用

请参阅下面的Try 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

这应该对你有用

dt <- unique(dt, by = c('V1', 'V2'))

dt保留数据。可使用的表格符号:

unique(df[, .(V1, V2, V3), nomatch=0 ])
就像这里一样


我还没有将此版本的速度与Magma的版本进行比较。

只有在未设置任何键的情况下,此功能才有效。我将对上面的问题进行编辑,以澄清这一点。Sorryas akrun在这里回答:第一个版本现在需要一个by=选项来work@PeterPan你发布的链接是dead@Andrie正如@PeterPan所指出的,这个解决方案不再有效<代码>数据。表
不再考虑键中的
unique()
。现在必须使用选项
unique(,by=c(keys))
。要知道altabq是正确的,keys中的内容必须用引号括起来。因此,您需要unique(dt,by=c(“V1”,“V2”))作为您的答案;现在存档为.Hi@MatthewDowle。是的,那会很方便。我认为你在FR中的评论也是正确的——如果键是唯一的,那么就可以忽略
use.key=FALSE
。data.table 1.9.6(毫无疑问是早期版本)有一个选项
by=
,可以用来覆盖键。设置
by=NULL
“使用所有列,其行为类似于类似的data.frame方法。”在不使用unique
dt[,.N,by=(V1,V2)][,1:2]
的情况下,OP希望删除数据表整行中的重复行,而不仅仅是键。这应该可以做到。
> 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(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
dt <- unique(dt, by = c('V1', 'V2'))
unique(df[, .(V1, V2, V3), nomatch=0 ])