【问题标题】:How can I revise my code to improve my processing speed如何修改代码以提高处理速度
【发布时间】:2016-06-03 14:33:57
【问题描述】:

我必须在大型矩阵的列中运行类似的代码。

set.seed(1)

my_vector <- runif( 10000 )

my_sums <- NULL

for ( l in 1:length( my_vector ) ) {

  current_result <- my_vector[ my_vector < runif( 1 ) ]

  my_sums[l] <- sum( current_result )

}

head(my_sums)
# [1]   21.45613 2248.31463 2650.46104   62.82708   11.11391   86.21950

Sys.time 结果:

   user  system elapsed 
   1.14    0.00    1.14

关于如何提高性能的任何想法?

【问题讨论】:

  • replicate(1e4, sum(my_vector[my_vector &lt; runif(1)])) 我及时得到了一点提升
  • 我还通过提前为my_sums 分配正确的大小来改进您的循环。 my_sums &lt;- numeric(10000)
  • @AntonioDamico:请不要随意添加rcpp标签。现在删除它。
  • 如果你想在一个大的matrix 中跨列运行类似的代码,最好提供一个与此数据结构匹配的可重现示例,例如matrixdata.framedata.table
  • 您应该单击此问题的优秀答案之一旁边的复选标记,将其标记为已接受。当您这样做时,复选标记将颜色变为绿色。投票也是对回答您的问题所付出的努力表示赞赏的标志。 :D

标签: r


【解决方案1】:

Matt Dowle's excellent data.table approach 在基础R

system.time({
  set.seed(1)
  my_vector <- runif(10000)
  x <- runif(10000)
  sorted <- sort(my_vector)
  ind <- findInterval(x, sorted) + 1
  my_sums <- c(0, cumsum(sorted))[ind]
})

#   user  system elapsed 
#      0       0       0 

head(my_sums)
#[1]   21.45613 2248.31463 2650.46104   62.82708   11.11391   86.21950

【讨论】:

  • +1 表示超快。但是,您应该更正一个错误。 x 小于 min(my_vector) 的值将返回索引 0。子集 cumsum(sorted)[ind=0] 将为此类值生成 NULL,从而从 my_sums 向量中删除这些值,因此将比 my_vector 短。解决方案是使用my_sums &lt;- c(0,cumsum(sorted))[ind+1]
  • @dww 按建议更正。谢谢。
  • 为什么将0 编辑为-Inf? @dww 的解决方案在上面的评论中返回 0x&lt;min(my_vector) 是正确的。但现在它会为那些返回-Inf
  • @MattDowle,我的脑海里有findInterval(x, c(-Inf, sorted))。感谢您指出。
【解决方案2】:
require(data.table)

system.time({
  set.seed(1)
  my_vector = runif(10000)
  DT = data.table(my_vector)
  setkey(DT, my_vector)
  DT[,cumsum:=cumsum(my_vector)]
  my_sums = DT[.(runif(10000)), cumsum, roll=TRUE]
  my_sums[is.na(my_sums)] = 0
})

head(my_sums)
# [1]   21.45613 2248.31463 2650.46104   62.82708   11.11391   86.21950

#   user  system elapsed 
#  0.004   0.000   0.004

【讨论】:

  • 不错的答案+1。其行为与 OP 中的代码不同的一个小问题:DT[.(x), cumsum, roll=TRUE]x &lt; min (my_vector) 返回 NA。而在这种情况下,OP 中的 sum() 给出 0。
  • @dww 很好发现。通过编辑修复以在 my_vector 的开头包含一个 0。时间没有变化。
  • @dww 或者,添加最后一行 my_sums[is.na(my_sums)] = 0 可以避免添加第一个 0。也不会更改时间。
  • @dww 所以我把它改成了替代品。
【解决方案3】:

sapply 呢?

temp <- sapply(seq_along(my_vector), function(l){

  current_result <- my_vector[ my_vector < runif( 1 ) ]
  my_sums[l] <- sum( current_result )

})

这有一些性能改进吗?

【讨论】:

    【解决方案4】:

    编辑:添加sort() 将我的时间减少到 0.74。在此示例中,对my_vector 进行排序所需的时间微不足道,但在较大/不同的数据上可能代价高昂。

    set.seed(1)
    
    my_vector <- runif( 10000 )
    n<-runif(10000)
    my_sums <- 1:10000
    system.time(my_vector<-sort(my_vector))
    
    #user  system elapsed 
    # 0       0       0 
    # my_vector is now sorted.
    
    
    system.time(
    for ( l in 1:length( my_vector ) ) {
    
    my_sums[l] <- sum(my_vector[my_vector < n[l]])
    })
    
    # user  system elapsed 
    # 0.73    0.00    0.74 
    
    head(my_sums)
    # [1]   21.4561 2248.3146 2650.4610   62.8271   11.1139   86.2195
    

    【讨论】:

      【解决方案5】:

      由于您想在大型矩阵的列中应用相同的函数,我建议这样做:

      dt <- data.table( my_vector1 = runif( 1000000 ),
                        my_vector2 = runif( 1000000 ),
                        my_vector3 = runif( 1000000 ))
      
      cols <- paste0(names(dt),"_csum")
      
      setkey(dt)
      
      dt[, (cols) := lapply (.SD, function(x)  cumsum(x) )]
      
      
      > head(dt)
      #>      my_vector1 my_vector2 my_vector3 my_vector1_csum my_vector2_csum my_vector3_csum
      #> 1: 7.664785e-07 0.47817820  0.9008552    7.664785e-07       0.4781782       0.9008552
      #> 2: 8.875504e-07 0.24142375  0.9849384    1.654029e-06       0.7196019       1.8857936
      #> 3: 1.326203e-06 0.48592786  0.3791094    2.980232e-06       1.2055298       2.2649030
      #> 4: 2.730172e-06 0.76847160  0.5732031    5.710404e-06       1.9740014       2.8381061
      #> 5: 4.655216e-06 0.01094117  0.5120915    1.036562e-05       1.9849426       3.3501976
      

      此外,library profvis 确实有助于识别代码中每一行的时间和内存消耗。 Example here.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-12-14
        • 2019-10-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多