我有一个像这样的data.table:
dt<-data.table(v1=rep(c('a','b','c'),4), v2=rep(c(1,2),6))
v1 v2
1: a 1
2: b 2
3: c 1
4: a 2
5: b 1
6: c 2
7: a 1
8: b 2
9: c 1
10: a 2
11: b 1
12: c 2
我需要删除所有具有相同v1但不同v2的行(v1和v2的每个组合中的第一行除外)。在此示例中,应删除行4-6和10-12。我怎么能这样做?
答案 0 :(得分:3)
我认为这是有效的:
dt[, v2[v2 == v2[1]], by = v1]
# v1 V1
#1: a 1
#2: a 1
#3: b 2
#4: b 2
#5: c 1
#6: c 1
答案 1 :(得分:2)
这个怎么样?
tmp = dt[dt[, list(I=.I[1]), by=list(v1)]$I]
setkey(dt)[tmp]
v1 v2
1: a 1
2: a 1
3: b 2
4: b 2
5: c 1
6: c 1
更大的数据和基准测试:
# create some data
require(data.table)
require(microbenchmark)
set.seed(1)
ff <- function() paste0(sample(letters, sample(5:8, 1), TRUE), collapse="")
ll <- unique(replicate(1e4, ff()))
DT <- data.table(v1=sample(ll, 1e6, TRUE), v2=sample(1:1e4, 1e6, TRUE))
# add functions
eddi <- function(dt=copy(DT)) {
dt[, list(v2=v2[v2 == v2[1]]), by = v1]
}
andrey <- function(dt=copy(DT)) {
dt[, .SD[v2 == v2[1],], by = v1]
}
arun <- function(dt=copy(DT)) {
tmp = dt[dt[, list(I=.I[1]), by=list(v1)]$I]
setkey(dt)[tmp]
}
# benchmark
microbenchmark(a1 <- eddi(), a2 <- andrey(), a3 <- arun(), times=2)
Unit: milliseconds
expr min lq median uq max neval
a1 <- eddi() 342.4429 342.4429 348.1604 353.8780 353.8780 2
a2 <- andrey() 5810.8947 5810.8947 5829.0742 5847.2537 5847.2537 2
a3 <- arun() 494.6861 494.6861 509.3022 523.9182 523.9182 2
setkey(a3, NULL)
> identical(a1, a2) # [1] TRUE
> identical(a1, a3) # [1] TRUE
答案 2 :(得分:1)
您可以尝试使用mult
参数。我不确定setkeyv
是否会影响您选择的行,请在使用之前检查一下 -
setkeyv(dt,c('v1'))
firstocc <- dt[unique(dt),,mult="first"][,v2.1 := NULL]
setkeyv(dt,c('v1','v2'))
setkeyv(firstocc,c('v1','v2'))
dt[firstocc]