假设我有一个带有3列密钥的data.table。例如,让我们说我们有时间嵌套在学校里的学生身上。
dt <- data.table(expand.grid(schools = 200:210, students = 1:100, time = 1:5),
key = c("schools", "students", "time"))
并说我想获取仅包含时间5的数据子集。我知道我可以使用subset
:
time.5 <- subset(dt, wave == 5)
或者我可以进行矢量扫描:
time.5 <- dt[wave == 5]
但那些不是&#34; data.table方式&#34; - 我想利用二进制搜索的速度。由于我的密钥中有3列,因此使用unique
产生的结果不正确:
dt[.(unique(schools), unique(students), 5)]
有什么想法吗?
答案 0 :(得分:2)
您可以尝试
setkey(dt, time)
dt[J(5)]
all( dt[J(5)][,time]==5)
#[1] TRUE
dt1 <- data.table(expand.grid(schools=200:450, students=1:600,time=1:50),
key=c('schools', 'students', 'time'))
f1 <- function(){dt1[time==5]}
f2 <- function(){setkey(dt1, time)
new.dt <- dt1[J(5)]
setkeyv(new.dt, colnames(dt1))
}
f3 <- function() {setkey(dt1, time)
dt1[J(5)]}
microbenchmark(f1(), f2(), f3(), unit='relative', times=20L)
#Unit: relative
#expr min lq mean median uq max neval cld
#f1() 3.188559 3.240377 3.342936 3.218387 3.224352 5.319811 20 b
#f2() 1.050202 1.083136 1.081707 1.089292 1.087572 1.129741 20 a
#f3() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 20 a
答案 1 :(得分:0)
如果查询性能是主要因素,您还可以加快@ akrun的解决方案。
# install_github("jangorecki/dwtools")
# or just source: https://github.com/jangorecki/dwtools/blob/master/R/idxv.R
library(dwtools)
# instead of single key you can define multiple to be used automatically without the need to re-setkey
Idx = list(
c('schools', 'students', 'time'),
c('time')
)
IDX <- idxv(dt1, Idx)
f4 <- function(){
dt1[CJI(IDX,TRUE,TRUE,5)]
}
microbenchmark(f4(), f1(), f2(), f3(), unit='relative', times=1L)
#Unit: relative
#expr min lq mean median uq max neval
#f4() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1
#f1() 6.431114 6.431114 6.431114 6.431114 6.431114 6.431114 1
#f2() 2.320577 2.320577 2.320577 2.320577 2.320577 2.320577 1
#f3() 23.706655 23.706655 23.706655 23.706655 23.706655 23.706655 1
如果我错了,请纠正我,但似乎f3()
计算在微观标记times > 1L
时重复使用它的键。
请注意,多个索引( Idx )需要大量内存。