【问题标题】:Improving data.table subsetting performance提高 data.table 子集性能
【发布时间】:2019-05-28 18:47:54
【问题描述】:

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

【问题讨论】:

  • 考虑使用并行包进行蒙特卡罗模拟,在多核上运行代码
  • 我可以理解较慢的子集,因为 [i, j] 可以根据表达式做很多事情,初始检查肯定会有开销。较慢的搜索确实让我觉得奇怪。
  • 如果您的 x.dt 在这么多次迭代中是相同的,并且查找/搜索是针对像 a 这样的整数,则只需预先计算子集并将它们存储在列表中。 bs = split(x.dt$b, x.dt$a) 并根据需要访问 bs[[1]]。

标签: r performance data.table subset benchmarking


【解决方案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]
}
})

结果:

【讨论】:

  • 在小数据集的搜索中,“时间”没有多大意义。即使它需要“更长”的时间,它仍然是纳秒,所以没有人真正关心。当涉及到纳秒时,data.table 确实有开销。虽然,时间只有在我们扩展到毫秒/秒/等时才重要——当它变得痛苦时,这就是 data.table 闪耀的时候,这首先是它背后的想法。没有人会创建一个包来提高 R 中的纳秒级性能
  • 因此,您关于“data.table 每次搜索有很多开销”的说法是毫无意义的。您应该多次(不是一次)测试大型数据集,然后查看它有多少开销。
猜你喜欢
  • 2015-09-07
  • 1970-01-01
  • 2013-12-27
  • 1970-01-01
  • 1970-01-01
  • 2016-02-18
  • 1970-01-01
  • 1970-01-01
  • 2012-06-17
相关资源
最近更新 更多