【问题标题】:For-loop vs foreach vs apply and the fastest objects for data manipulation?For-loop vs foreach vs apply 以及最快的数据操作对象?
【发布时间】:2018-08-16 19:08:22
【问题描述】:

我希望比我更有知识的人能帮助优化这段代码。我尝试了许多方法,包括使用 doparallel(和雪)和编译器的 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 的生成,这在计算上并不复杂。这就是我怀疑优化可能带来最大好处的地方。

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

我无法确定细节,而且我不相信这是最好的方法。所以在我追逐这只野鹅之前,我认为社区可能能够引导我朝着最好的方向前进。

【问题讨论】:

    标签: r performance for-loop optimization apply


    【解决方案1】:

    rank 花费的时间最多。可以将计算时间减少 50% 以上,即将base::rankfor 循环更改为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
    

    【讨论】:

    • 非常感谢您的评论!我昨天尝试了几次,但没有看到任何改善。我今天在进入 RMD 后再次尝试,希望能排除一些错误,但得到了同样的结果 - 没有任何改进。旧时间:7.4 - 7.9 分钟,新时间:7.8-7.9 分钟。我认为方差只是随机的。我确实认为你在做某事。我必须弄清楚我的物品与您的物品有何不同。
    • 我注意到在生成上面显示的 df 方面有巨大的性能提升。它几乎是立即生成的。不幸的是,当我运行分析 (c_score_new()) 时,我仍然必须在循环中从该 df 中获取列,并且我失去了 100% 的时间(仍然总计约 7.5 分钟)。我希望我能给你的不仅仅是一个赞成票;非常感谢您为我看这个!
    • 不幸的是,如果没有更多关于 c_score_new 函数的详细信息,它很难优化。例如。请检查您在d_g_up$Symbold_g_down$Symbol 循环中提交的原因,但它们在for 循环中是不可变的。
    • 此外,您可以使用data.table 包,它允许额外的快速功能,包括哈希计算。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-23
    • 2019-02-23
    • 2015-07-08
    • 1970-01-01
    • 2018-06-26
    • 2020-11-12
    相关资源
    最近更新 更多