如果我理解正确,duplicated()
data.table
函数将返回一个逻辑向量,该向量不包含第一次出现的重复记录。标记第一次出现的最佳方法是什么?在base::duplicated()
的情况下,我只是通过取消逆序函数来解决这个问题:myDups <- (duplicated(x) | duplicated(x, fromLast=TRUE))
- 但在data.table::duplicated()
中,fromLast=TRUE
不包括在内(我不知道为什么) ...
P.S。好的,这是一个原始的例子
myDT <- fread(
"id,fB,fC
1, b1,c1
2, b2,c2
3, b1,c1
4, b3,c3
5, b1,c1
")
setkeyv(myDT, c('fB', 'fC'))
myDT[, fD:=duplicated(myDT)]
第1,3和5行都是重复的,但只有3和5将包含在duplicated
中,而我需要标记所有这些。
UPD。重要提示:我在下面接受的答案仅适用于键控表。如果要查找考虑所有列的重复记录,则必须明确setkey
所有这些列。到目前为止,我特别针对这种情况使用了以下解决方法:
dups1 <- duplicated(myDT);
dups2 <- duplicated(myDT, fromLast=T);
dups <- dups1 | dups2;
答案 0 :(得分:14)
许多年前,这是最快的答案(如果感兴趣,请参阅修订历史记录):
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
答案 1 :(得分:13)
这似乎有效:
> 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
特别是对于最大值那里发生了什么?
答案 2 :(得分:7)
第三种方法(对于这个小例子看来效率更高)
您可以明确调用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
的大小,那么key
方法就是明显的赢家
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
答案 3 :(得分:4)
从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日CRAN)
可能发生的变化
默认情况下,所有列现在都由unique(),duplicatelicated()和 uniqueN()data.table方法,#1284和#1841。恢复旧 behavior:options(datatable.old.unique.by.key = TRUE)。在这1年 恢复旧默认值的选项将被弃用,并显示警告。在 2年后该选项将被删除。请明确传递= key(DT) 为清楚起见。只有依赖于默认值的代码才会受到影响。 266 之前检查过使用data.table的CRAN和Bioconductor包 发布。 9需要改变并得到通知。任何代码行 这些检查将错过没有测试覆盖范围。任何 未检查CRAN或Bioconductor上的包。