我试图找到通过几个数字列对大型数据集进行子集化的最快方法.正如data.table所承诺的那样,二进制搜索所花费的时间比矢量扫描要快得多.但是,二进制搜索需要预先执行setkey.正如您在此代码中看到的那样,需要非常长的时间!考虑到这段时间后,矢量扫描要快得多:
set.seed(1)
n=10^7
nums <- round(runif(n,0,10000))
DT = data.table(s=sample(nums,n), exp=sample(nums,n),
init=sample(nums,n), contval=sample(nums,n))
this_s = DT[0.5*n,s]
this_exp = DT[0.5*n,exp]
this_init = DT[0.5*n,init]
system.time(ans1<-DT[s==this_s&exp==this_exp&init==this_init,4,with=FALSE])
# user system elapsed
# 0.65 0.01 0.67
system.time(setkey(DT,s,exp,init))
# user system elapsed
# 41.56 0.03 41.59
system.time(ans2<-DT[J(this_s,this_exp,this_init),4,with=FALSE])
# user system elapsed
# 0 0 0
identical(ans1,ans2)
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)
难道我做错了什么?我已经阅读了data.table常见问题解答等.任何帮助将不胜感激.
非常感谢.
这条线:
nums <- round(runif(n,0,10000))
Run Code Online (Sandbox Code Playgroud)
叶子不是nums类型.这有很大的不同.data.table常见问题和介绍适用于和列; 你不会看到这些类型的速度慢.例如 :numericintegerintegercharactersetkey
nums <- as.integer(round(runif(n,0,10000)))
...
setkey(DT,s,exp,init) # much faster now
Run Code Online (Sandbox Code Playgroud)
还有两点......
首先,在当前开发版本的data.table v1.8.11中,排序/排序操作要快得多.@jihoward对数字列的排序是一件非常耗时的操作.但是,它仍然在1.8.11中快了5-8倍(因为6通道基数顺序实现,请查看此帖子).比较setkey1.8.10和1.8.11之间的操作时间:
# v 1.8.11
system.time(setkey(DT,s,exp,init))
# user system elapsed
# 8.358 0.375 8.844
# v 1.8.10
system.time(setkey(DT,s,exp,init))
# user system elapsed
# 66.609 0.489 75.216
Run Code Online (Sandbox Code Playgroud)
它对我的系统提高了8.5倍.所以,我的猜测是你需要大约4.9秒.
其次,正如@Roland所提到的,如果你的目标是执行几个子集,那就是你要做的所有事情,那么当然做一个setkey是没有意义的,它必须找到顺序列然后重新排序整个data.table(通过引用使内存占用非常小,请查看此帖子以获取有关setkey的更多信息).