R 提高数据表子集设置性能

R 提高数据表子集设置性能,r,performance,data.table,subset,benchmarking,R,Performance,Data.table,Subset,Benchmarking,我正在运行一个大型蒙特卡罗模拟,我发现在我的代码中,设置/搜索数据是最慢的部分。为了测试一些备选方案,我使用dataframes、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)) # s

我正在运行一个大型蒙特卡罗模拟,我发现在我的代码中,设置/搜索数据是最慢的部分。为了测试一些备选方案,我使用dataframes、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的紧凑语法,我想知道我是否可以做些什么来提高它的性能。根据创作者的说法,它应该是超快速的。我是不是用错了?

经过更多的基准测试,我现在明白了这个问题。最快的包取决于我是在做很多小搜索还是一个大搜索。似乎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]
}
})
结果:

考虑使用并行软件包在多个coresI上运行蒙特卡罗模拟代码。我可以理解较慢的子集,因为
[i,j]
可以根据表达式执行许多操作,因此初始检查必须有开销。较慢的搜索确实让我感到奇怪。如果您的x.dt在这么多次迭代中都是相同的,并且查找/搜索的是像a这样的整数,只需预计算子集并将其存储在列表中
bs=split(x.dt$b,x.dt$a)
并根据需要进行类似
bs[[1]]
的访问。在小型数据集的搜索中,“时间”没有太多意义。即使需要“更长”的时间,它仍然是在纳秒,所以没有人真正关心。data.table在达到纳秒时确实有开销。尽管如此,只有当我们将时间缩放到毫秒/秒/等时,时间才有意义——这是痛苦的时刻,这是data.table闪耀的时刻,这是它背后的理念。在RHence中,没有人会为了在纳秒内提高性能而创建包,您的“data.table在每次搜索中都有很多开销”的语句是毫无意义的。您应该多次(而不是一次)测试大型数据集,然后看看它有多少开销。