For循环vs foreach vs应用以及最快的数据处理对象?

时间:2018-08-16 19:08:23

标签: r performance for-loop optimization apply

我希望比我自己更有知识的人可以帮助优化此代码。我尝试了许多方法,包括使用doparallel(和snow)和编译器的foreach,但我认为可能有更简单的方法来改进代码,例如将数据帧更改为数据表/矩阵,或者预加载空白对象向量在一个循环中的集合。

下面列出的大多数变量必须允许长度更改,具体取决于管道中的先前步骤。列出的尺寸是从1个示例中获取的,以显示相对大小。

s.ids =长度为66510的因数。更改为字符向量时尚未注意到速度的差异。

g.list =长度为978的字符向量。

l_signatures = 978x66511矩阵。

d_g_upd_g_down =具有与g.list相关的元数据的小型数据帧(nx10,n范围为5-200)

c_score_new()计算分数。它足够复杂,因此在这种情况下基本上是不可更改的。它期望e_signature具有2列,其中1列由g.list(“ ids”)组成,另一列为由rank(-1 * l_signatures[,as.character(id)], ties.method="random")

生成的相应“等级”
for (id in s.ids) {
    e_signature <- data.frame(g.list,
                              rank(-1 * l_signatures[, as.character(id)],
                                   ties.method="random"))    
    colnames(e_signature) <- c("ids","rank")
    d_scores <- c(d_scores, c_score_new(d_g_up$Symbol, d_g_down$Symbol, e_signature))
}

总计,这需要5-10分钟的时间进行计算,其中3-5分钟可归因于e_signature的生成,该签名在计算上并不复杂。在那我怀疑优化可能是最有利的。

如果我们执行循环以更有效的方式生成e_signature,然后在执行c_score_new()之前将结果合并为1个对象(978x66510),它会更快吗?

我在确定细节时遇到了麻烦,而且我不确定这是否是最好的方法。因此,在我追逐这头野鹅之前,我认为社区也许能够引导我朝着最佳方向发展。

1 个答案:

答案 0 :(得分:3)

rank花费的时间最多。可以将计算时间减少50%以上,即将base::rank循环的for更改为Rfast::colRanks,请参见以下内容:

library(microbenchmark)
library(Rfast)

n <- 978
m <- 40000 #66510

x <- matrix(rnorm(n * m), ncol = m)

microbenchmark(
  Initial = {
    for (i in 1:ncol(x)) { 
      base::rank(x[, i], ties.method = "random")
    }
  },
  Optimized = {

    colRanks(x, method = "min")
  },
  times = 1
)

输出:

Unit: seconds
      expr      min       lq     mean   median       uq      max neval
   Initial 8.092186 8.092186 8.092186 8.092186 8.092186 8.092186     1
 Optimized 3.397526 3.397526 3.397526 3.397526 3.397526 3.397526     1