簡體   English   中英

計算具有許多零的數組總和的最有效方法?

[英]Most efficient way to calculate sum of array with many zeroes?

我有一個nm列的矩陣。

我想將 function f(x)應用於矩陣中的每個元素,然后逐行求和(因此 output 是向量)。

但是,對於負x ,function 值f(x)為零。

所以,現在,我正在遍歷每一行,然后應用sum(f(row_i))類的東西。

這行得通,但我怎樣才能更快地做到這一點?

具體來說,我可以以某種方式使用我知道f(x)對於負x為零的事實(因此不會添加到sum中)嗎? 或者我可以以某種方式擺脫對行的for循環嗎? 我試過sapply但它並沒有加快速度。

我不確定這是最快的方法,但它可能會非常有效。

基本上使用向量化的 function rowSums進行求和,購買先將矩陣轉換為僅正值。 如果您的 function f(x)是矢量化的,您可以先將此 function 應用於整個矩陣,然后再使用rowSums

n <- 1e6
ncol = 10
dat <- matrix(rnorm(n), ncol= ncol)
system.time(rowSums(ifelse(dat > 0, dat, 0)) #or rowSums(f(dat)))
#output
   user  system elapsed 
   0.02    0.03    0.04 

這是一種應用/應用方法,與更幼稚的循環方法進行比較。 加速大約是 3 倍(盡管取決於矩陣中負數的百分比)。 如果您正在做的循環更加幼稚(例如,沒有預分配),那么加速會更大,但在這種情況下,問題實際上在於循環本身,而不是缺乏過濾每一行。 最好的方法是盡可能編寫完全矢量化的代碼,並完全跳過循環或 sapply。 如果沒有更多細節,就不可能說出這對您的情況意味着什么。 通過比較,我添加了使用rowSums()的完全矢量化版本如何工作。 如您所見,這就是真正的加速所在:

#functions to create a vector of sums where f is applied to the rows of A
#The first method is a naive loop, the second takes advantage of the fact that
#x < 0 imples f(x) == 0

method1 <- function(A,f){
  m <- nrow(A)
  n <- ncol(A)
  v <- rep(0,m)
  for(i in 1:m){
    row <- rep(0,n)
    for(j in 1:n){
      row[j] = f(A[i,j])
    }
    v[i] = sum(row)
  }
  v
}

method2 <- function(A,f){
  apply(A,1,function(row){sum(sapply(row[row >= 0],f))})
}

#for testing:

f <- function(x) max(0,x)^2
g <- function(x) pmax(x,0)^2 #vectorized version of f
A <- matrix(runif(10000,-10,2),nrow = 100)

library(microbenchmark)
print(microbenchmark(method1(A,f),method2(A,f),rowSums(g(A))))

典型的 output(在我的機器上):

Unit: microseconds
          expr       min         lq       mean     median        uq       max neval
 method1(A, f) 13826.824 14672.9285 16076.5778 15342.0195 16916.631 33829.384   100
 method2(A, f)  5629.886  6009.6550  6687.8325  6247.3185  7117.401 14411.815   100
 rowSums(g(A))   217.566   249.6535   315.7482   271.8685   303.075  2918.966   100

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM