分裂应用组合的更快替代方案

时间:2014-08-15 06:31:03

标签: r performance data-structures plyr

短版

由于分割和组合所需的开销,

plyr::dlply的分割 - 应用 - 组合似乎效率低下。我错了,还是有更好/更快的方式?


长版本

我在R中拟合了几千个向量自动回归,其功能类似于vars::VAR的美化包装/提取器。我只是称之为estim

现在,我的数据是“长”格式,例如

dd <- structure(list(id = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 
3L, 3L), time = c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 
4L), x = c(0L, 0L, 1L, 0L, 6L, 2L, 3L, 2L, 3L, 3L, 1L, 1L), y = c(0L, 
1L, 1L, 0L, 2L, 0L, 2L, 0L, 0L, 3L, 3L, 0L)), .Names = c("id", 
"time", "x", "y"), row.names = c(NA, -12L), class = "data.frame")

我正在处理output <- plyr::dlply(dd, .(id), myFun)

每个ID有大约4,800个ID和182个时间点,我得到了

system.time(output <- plyr::dlply(dd, .(id), estimate, .parallel = FALSE))
#   user  system elapsed 
# 37.357   0.730  38.048 

registerDoMC(detectCores() - 1) # I have 4 cores
system.time(output <- plyr::dlply(dd, .(id), estimate, .parallel = TRUE))
#   user  system elapsed 
# 57.234   6.710  23.593 

在我的MacBook上(2.8 GHz i7,内存为16 GB)。

并行执行并不能节省我希望的时间。这告诉我,此操作的“慢”部分不在计算estimate中,而是在dplyr使用的拆分和组合步骤中的某处。

split-apply-combine范例非常适合交互式和中等规模使用(至少在这种情况下比循环要快得多),但我怀疑有更好的方法。我应该将数据重新整形为“宽”格式,例如

dd.wide <- structure(list(time = 1:4, `1_x` = c(0L, 0L, 1L, 0L), `1_y` = c(0L, 
1L, 1L, 0L), `2_x` = c(6L, 2L, 3L, 2L), `2_y` = c(2L, 0L, 2L, 
0L), `3_x` = c(3L, 3L, 1L, 1L), `3_y` = c(0L, 3L, 3L, 0L)), .Names = c("time", 
"1_x", "1_y", "2_x", "2_y", "3_x", "3_y"), row.names = c(NA, 
-4L), class = "data.frame")

然后将myFun应用于列对吗?

有没有更有效的方法来实现这一目标?或者,我可以在这里更好地利用并行化吗?或者它的速度和它一样快?

最后,让我们说现在我想做

estim2 <- function(param) ddply(dd, .(id), estim, foo = param)
output.list <- lapply(1:10, estim2)

答案是否会改变?我对以这种嵌套循环并行化的“正确”方式特别感兴趣,尽管我确信之前已经在这个网站上进行过覆盖。

1 个答案:

答案 0 :(得分:-1)

根据评论,我对开销的怀疑是错误的。内部函数执行需要约7微秒,而.007 * 4800 = 33.6秒。

关于:

  

与plyr :: dlply的split-apply-combine似乎效率低,因为拆分和组合需要开销。我错了,还是有更好/更快的方式?

答案是

  

如果没有让内部功能更快,那么期待严重的加速可能是不合理的。

事实上,我错了。