2012-11-08 19 views
7

行列の各列の加重和が必要です。行列の列の加重和を取る最速の方法R

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)は、適用コールよりも高速です。

私はこの操作をしばしば(大きなマトリックス上で)行います。したがって、最も効率的な実装に関するアドバイスを探しています。理想的には、colSums(またはrowSums)にウェイトを渡すことができれば素晴らしいでしょう。

ありがとうございました。

答えて

8

colSums*は、内部またはプリミティブ関数であり、あなたが

weights %*% data 

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

applyアプローチよりもはるかに高速になります行列の乗算方法は高速ではないようですが、サイズが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 
の一時オブジェクトを作成することは避けられます
+0

ありがとうございます。 – Anirban

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 
関連する問題