我正在运行大型蒙特卡洛模拟,我发现子设置/搜索数据是代码中最慢的部分。为了测试一些替代方案,我用数据帧,data.table和矩阵对性能进行了基准测试。 这是基准代码:
library(data.table)
#install.packages('profvis')
library(profvis)
x.df = data.frame(a=sample(1:10,10000,replace=T), b=sample(1:10,10000,replace=T)) # set up a dataframe
x.dt = as.data.table(x.df) # a data.table
setkey(x.dt,a) # set key for faster searches
x.mat = as.matrix(x.df) # a matrix
profvis({
for (i in 1:10000) {
# test simple subsetting
xsubset.mat = x.mat[100:200,2]
xsubset.df = x.df[100:200,2]
xsubset.dt = x.dt[100:200,2]
# test search preformance
xsearch.mat = x.mat[which(x.df$a==10),2]
xsearch.df = x.df[which(x.df$a==10),2]
xsearch.dt = x.dt[.(10),2]
}
})
这是我的结果:
认真地说,我喜欢data.table的紧凑语法,并且我想知道是否可以做些什么来提高其性能。根据创作者的说法,它应该超级快。我使用不正确吗?
答案 0 :(得分:1)
经过一些基准测试之后,我现在了解了这个问题。最快的程序包取决于我要进行多次小型搜索还是一次大型搜索。似乎data.table每次搜索有很多开销,这使其更适合于处理一个大型表,而对于小型表则没有太多搜索。
考虑以下代码,并与原始代码进行比较:
# make a giant table, but search it only once:
x.df = data.frame(a=sample(1:10,100000000,replace=T), b=sample(1:10,100000000,replace=T))
x.dt = as.data.table(x.df)
setkey(x.dt,a)
x.mat = as.matrix(x.df)
profvis({
for (i in 1:1) {
xsubset.mat = x.mat[100:200,2]
xsubset.df = x.df[100:200,2]
xsubset.dt = x.dt[100:200,2]
xsearch.mat = x.mat[which(x.df$a==10),2]
xsearch.df = x.df[which(x.df$a==10),2]
xsearch.dt = x.dt[.(10),2]
}
})