R 在data.table中查找*所有*重复记录(不是全部,而是一条)

R 在data.table中查找*所有*重复记录(不是全部,而是一条),r,data.table,R,Data.table,如果我理解正确,duplicated()函数用于数据。表返回一个不包含重复记录第一次出现的逻辑向量。什么是最好的方式来标记这第一次发生呢?在base::duplicated()的情况下,我简单地通过使用反序函数进行析取来解决这个问题:myDups这似乎有效: > myDT[unique(myDT),fD:=.N>1] > myDT id fB fC fD 1: 1 b1 c1 TRUE 2: 3 b1 c1 TRUE 3: 5 b1 c1 TRU

如果我理解正确,
duplicated()
函数用于
数据。表
返回一个不包含重复记录第一次出现的逻辑向量。什么是最好的方式来标记这第一次发生呢?在
base::duplicated()
的情况下,我简单地通过使用反序函数进行析取来解决这个问题:
myDups这似乎有效:

> myDT[unique(myDT),fD:=.N>1]
> myDT
   id  fB fC    fD
1:  1  b1 c1  TRUE
2:  3  b1 c1  TRUE
3:  5  b1 c1  TRUE
4:  2  b2 c2 FALSE
5:  4  b3 c3 FALSE
感谢@flodel,更好的方法是:

> myDT[, fD := .N > 1, by = key(myDT)]
> myDT
   id  fB fC    fD
1:  1  b1 c1  TRUE
2:  3  b1 c1  TRUE
3:  5  b1 c1  TRUE
4:  2  b2 c2 FALSE
5:  4  b3 c3 FALSE
效率差异很大:

> microbenchmark(
    key=myDT[, fD := .N > 1, by = key(myDT)],
    unique=myDT[unique(myDT),fD:=.N>1])
Unit: microseconds
   expr      min       lq    median        uq       max neval
    key  679.874  715.700  735.0575  773.7595  1825.437   100
 unique 1417.845 1485.913 1522.7475 1567.9065 24053.645   100
特别是对于最大值。这是怎么回事?

第三种方法(在这个小例子中似乎更有效)

您可以显式调用
duplicated.data.frame

myDT[,fD := duplicated.data.frame(.SD)|duplicated.data.frame(.SD, fromLast=TRUE),
  .SDcols = key(myDT)]


 microbenchmark(
   key=myDT[, fD := .N > 1, by = key(myDT)],
   unique=myDT[unique(myDT),fD:=.N>1], 
  dup = myDT[,fD := duplicated.data.frame(.SD)|duplicated.data.frame(.SD, fromLast=TRUE), 
    .SDcols = key(myDT)])
## Unit: microseconds
##    expr      min        lq   median        uq       max neval
##     key  556.608  575.9265  588.906  600.9795 27713.242   100
##  unique 1112.913 1164.8310 1183.244 1216.9000  2263.557   100
##     dup  420.173  436.3220  448.396  461.3750   699.986   100
如果我们扩大样本
data.table
的大小,那么
方法显然是赢家

 myDT <- data.table(id = sample(1e6), 
  fB = sample(seq_len(1e3), size= 1e6, replace=TRUE), 
  fC = sample(seq_len(1e3), size= 1e6,replace=TRUE ))
setkeyv(myDT, c('fB', 'fC'))

microbenchmark(
  key=myDT[, fD := .N > 1, by = key(myDT)],
  unique=myDT[unique(myDT),fD:=.N>1], 
  dup = myDT[,fD := duplicated.data.frame(.SD)|duplicated.data.frame(.SD, fromLast=TRUE),
   .SDcols = key(myDT)],times=10)
## Unit: milliseconds
##    expr       min        lq    median        uq       max neval
##     key  355.9258  358.1764  360.7628  450.9218  500.8360    10
##  unique  451.3794  458.0258  483.3655  519.3341  553.2515    10
##     dup 1690.1579 1721.5784 1775.5948 1826.0298 1845.4012    10
myDT 1,by=key(myDT)],
唯一=myDT[唯一(myDT),fD:=.N>1],
dup=myDT[,fD:=duplicated.data.frame(.SD)| duplicated.data.frame(.SD,fromLast=TRUE),
.SDcols=key(myDT)],时间=10)
##单位:毫秒
##expr最小lq中值uq最大neval
##图例355.9258 358.1764 360.7628 450.9218 500.8360 10
##独特的451.3794 458.0258 483.3655 519.3341 553.2515 10
##dup 1690.1579 1721.5784 1775.5948 1826.0298 1845.4012 10

许多年前,这是最快的答案(如果有兴趣,请参阅修订历史):

然而,自那时以来,内部发生了许多变化,对同一订单做出了许多选择:

myDT <- data.table(id = sample(1e6), 
                   fB = sample(seq_len(1e3), size= 1e6, replace=TRUE), 
                   fC = sample(seq_len(1e3), size= 1e6,replace=TRUE ))
setkey(myDT, fB, fC)

microbenchmark(
   key=myDT[, fD := .N > 1, by = key(myDT)],
   unique=myDT[unique(myDT, by = key(myDT)),fD:=.N>1], 
   dup = myDT[,fD := duplicated.data.frame(.SD)|duplicated.data.frame(.SD, fromLast=TRUE),
              .SDcols = key(myDT)],
   dup2 = {dups = duplicated(myDT, by = key(myDT)); myDT[, fD := dups | c(tail(dups, -1L), FALSE)]},
   dup3 = {dups = duplicated(myDT, by = key(myDT)); myDT[, fD := dups | c(dups[-1L], FALSE)]},
   times=10)

#   expr       min        lq      mean    median        uq       max neval
#    key  523.3568  567.5372  632.2379  578.1474  678.4399  886.8199    10
# unique  189.7692  196.0417  215.4985  210.5258  224.4306  290.2597    10
#    dup 4440.8395 4685.1862 4786.6176 4752.8271 4900.4952 5148.3648    10
#   dup2  143.2756  153.3738  236.4034  161.2133  318.1504  419.4082    10
#   dup3  144.1497  150.9244  193.3058  166.9541  178.0061  460.5448    10
myDT 1,by=key(myDT)],
unique=myDT[unique(myDT,by=key(myDT)),fD:=.N>1],
dup=myDT[,fD:=duplicated.data.frame(.SD)| duplicated.data.frame(.SD,fromLast=TRUE),
.SDcols=密钥(myDT)],
dup2={dups=duplicated(myDT,by=key(myDT));myDT[,fD:=dups|c(tail(dups,-1L),FALSE)],
dup3={dups=duplicated(myDT,by=key(myDT));myDT[,fD:=dups|c(dups[-1L],FALSE)],
次数=10)
#expr最小lq平均uq最大neval
#图例523.3568 567.5372 632.2379 578.1474 678.4399 886.8199 10
#唯一189.7692 196.0417 215.4985 210.5258 224.4306 290.2597 10
#dup 4440.8395 4685.1862 4786.6176 4752.8271 4900.4952 5148.3648 10
#dup2 143.2756 153.3738 236.4034 161.2133 318.1504 419.4082 10
#dup3 144.1497 150.9244 193.3058 166.9541 178.0061 460.5448 10

自data.table 1.9.8版起,eddi的解决方案需要修改为:

dups = duplicated(myDT, by = key(myDT));
myDT[, fD := dups | c(tail(dups, -1), FALSE)]
自:

v1.9.8的变化(2016年11月25日)

潜在的破坏性变化

默认情况下,unique()、duplicated()和 uniqueN()data.table方法,#1284和#1841。复古 行为:选项(datatable.old.unique.by.key=TRUE)。今年1年内 用于恢复旧默认值的选项将被弃用,并带有警告。在里面 2年后,该选项将被删除。请显式通过=键(DT) 为了清楚起见。只有依赖默认值的代码才受影响。266 使用data.table的CRAN和Bioconductor封装之前进行了检查 释放。9需要更改,并已通知。任何代码行 如果没有测试,这些检查将错过覆盖范围。任何 未检查不在CRAN或Bioconductor上的包装


可以有>1个类型和>1个令牌吗?对不起,我不明白这个问题-这里的类型和令牌是什么?;对不起,我的意思是,在您的示例中,只有一种行是重复的(即,“b1,c1”)。但是会不会有,例如,“6,b2,c2”&如果是的话,你也想得到它吗?谢谢你的指点!是的,当然,应该包括多个“b2,c2”-以及任何具有重复项的记录。@VasilyA接受的答案不依赖于设置的键。您可以根据您喜欢的任何列集检查重复项,而不考虑键,例如
duplicated(x,by=my\cols)
duplicated(x,by=NULL)
。后一种情况下的行为包含在文档中,并且似乎是您所追求的关于密钥的行为。对于您的
nrow(myDT):1
想法,请使用
fromLast
参数。哦,等等,我知道你对被接受的答案是正确的,但我认为我关于fromLast的观点可能会有所帮助。谢谢,它确实有效。我只是想避免使用
unique
,因为它返回整个表,而不仅仅是逻辑向量,所以我担心这不是处理大型表的最佳方法。我很高兴它赢了。这是我不必搜索就能想到的唯一方法。:)哇,太棒了!如果我理解正确,这里我们使用这样一个事实,即在
setkey
之后,我们的重复项被分组,因此我们可以简单地将
复制的
向量“移位”一个位置-对吗?通过避免调用
tail
,以及相关的方法调度时间,您可以使这一过程更快。(我已经在你的答案中添加了这一点)(不确定是否有人会注意到对这么老的帖子的评论)-我刚刚意识到,所有这些方法都只适用于键控表,也就是说,如果我想包括所有要比较的列,我必须显式地为它们设置键。如果我错了,请纠正我。@VasilyA正确,或者使用新的“on”参数
dups = duplicated(myDT, by = key(myDT));
myDT[, fD := dups | c(tail(dups, -1), FALSE)]
myDT <- data.table(id = sample(1e6), 
                   fB = sample(seq_len(1e3), size= 1e6, replace=TRUE), 
                   fC = sample(seq_len(1e3), size= 1e6,replace=TRUE ))
setkey(myDT, fB, fC)

microbenchmark(
   key=myDT[, fD := .N > 1, by = key(myDT)],
   unique=myDT[unique(myDT, by = key(myDT)),fD:=.N>1], 
   dup = myDT[,fD := duplicated.data.frame(.SD)|duplicated.data.frame(.SD, fromLast=TRUE),
              .SDcols = key(myDT)],
   dup2 = {dups = duplicated(myDT, by = key(myDT)); myDT[, fD := dups | c(tail(dups, -1L), FALSE)]},
   dup3 = {dups = duplicated(myDT, by = key(myDT)); myDT[, fD := dups | c(dups[-1L], FALSE)]},
   times=10)

#   expr       min        lq      mean    median        uq       max neval
#    key  523.3568  567.5372  632.2379  578.1474  678.4399  886.8199    10
# unique  189.7692  196.0417  215.4985  210.5258  224.4306  290.2597    10
#    dup 4440.8395 4685.1862 4786.6176 4752.8271 4900.4952 5148.3648    10
#   dup2  143.2756  153.3738  236.4034  161.2133  318.1504  419.4082    10
#   dup3  144.1497  150.9244  193.3058  166.9541  178.0061  460.5448    10
dups = duplicated(myDT, by = key(myDT));
myDT[, fD := dups | c(tail(dups, -1), FALSE)]