8

行列の各列の加重合計が必要です。

data <- matrix(1:2e7,1e7,2) # warning large number, will eat up >100 megs of memory
weights <- 1:1e7/1e5
system.time(colSums(data*weights))
system.time(apply(data,2,function(x) sum(x*weights)))
all.equal(colSums(data*weights), apply(data,2,function(x) sum(x*weights)))

通常colSums(data*weights)、apply 呼び出しよりも高速です。

私はこの操作を頻繁に (大規模なマトリックスで) 行います。したがって、最も効率的な実装に関するアドバイスを探しています。理想的には、重みを colSums (または rowSums) に渡すことができれば最高でした。

ありがとう、洞察に感謝します!

4

2 に答える 2

8

colSumsとは両方とも内部関数またはプリミティブ関数であり、アプローチ*よりもはるかに高速になりますapply

あなたが試すことができる別のアプローチは、探しているようにいくつかの基本的な行列代数を使用することです

 weights %*% data

行列乗算法は高速ではないように見えますが、一時的なオブジェクトのサイズの作成を回避しますdata

system.time({.y <- colSums(data * weights)})
##  user  system elapsed 
##  0.12    0.03    0.16 


system.time({.x <- weights %*% data})
##   user  system elapsed 
##   0.20    0.05    0.25 
于 2012-11-08T02:33:51.037 に答える
3

Rcpp を使用すると、パフォーマンスが向上します (特に列数が多い場合)。

library(Rcpp)
library(inline)
src <- '
 Rcpp::NumericMatrix dataR(data);
 Rcpp::NumericVector weightsR(weights);
 int ncol = dataR.ncol();
 Rcpp::NumericVector sumR(ncol);
 for (int col = 0; col<ncol; col++){
   sumR[col] = Rcpp::sum(dataR( _, col)*weightsR);
 }
 return Rcpp::wrap(sumR);'

weighted.colSums <- cxxfunction(
  signature(data="numeric", weights="numeric"), src, plugin="Rcpp")
data <- matrix(as.numeric(1:1e7),1e5,100) # warning large object
weights <- 1:1e5/1e5
all.equal(colSums(data*weights), weighted.colSums(data, weights))
## [1] TRUE
print(system.time(colSums(data*weights)))
##   user  system elapsed 
##  0.065   0.001   0.064 
print(system.time(as.vector(weighted.colSums(data, weights))))
##   user  system elapsed 
##  0.019   0.001   0.019 
all.equal(as.vector(weights %*% data), weighted.colSums(data, weights))
## [1] TRUE
print(system.time(weights %*% data))
##   user  system elapsed 
##  0.066   0.001   0.066 
于 2012-11-08T09:33:36.847 に答える