大きな行列の要約統計を計算するために、Rcpp と RcppArmadillo をテストしてきました。これは、400 万行、45 列で、ベースの R colMeans または Armadillo よりもはるかに高速 (5 倍または 10 倍) でした。
colMeansRcpp <- cxxfunction(signature(X_="integer"),
plugin='Rcpp',
body='
Rcpp::IntegerMatrix X = X_;
int ncol = X.ncol(); int nrow = X.nrow();
Rcpp::NumericVector out(ncol);
for(int col = 0; col < ncol; col++){
out[col]=Rcpp::sum(X(_, col));
}
return wrap(out/nrow);
')
私は本当に、プロットのために中央値とおそらく他の分位数を計算したいと思っています. アルマジロは少し遅いように見えるので、上記のようなコードでインプレースソートを実行したかったのですが、正しい構文を取得できません...これが私が試みていることです..
# OK I'm aware this floor(nrow/2) is not **absolutely** correct
# I'm simplifying here
colMedianRcpp <- cxxfunction(signature(X_="integer"),
plugin='Rcpp',
body='
Rcpp::IntegerMatrix X = clone(X_);
int ncol = X.ncol(); int nrow = X.nrow();
Rcpp::NumericVector out(ncol);
for(int col = 0; col < ncol; col++){
X(_,col)= std::sort((X_,col).begin, (X_,col).end));
out[col]=X(floor(nrow/2), col));
}
return wrap(out);
')
基本的にはラインです
X(_,col)= std::sort((X_,col).begin, (X_,col).end));
このRcppシュガーとstd C++の混合物で「列をその場でソートする」を表現する方法がわかりません。申し訳ありませんが、私がやっていることは間違っていることがわかりますが、正しい構文のヒントは素敵です.
ps R オブジェクトを変更しないように、この clone() を実行する必要がありますか?
EDIT RcppArmadilloコードとベンチマーク比較を追加して、以下の回答/コメントに対処します。ベンチマークは、迅速な返信のために 50k 行のみでしたが、それ以上の行でも同様だったことを思い出します。私はあなたが Rcpp の作者であることを理解しています.. お時間をいただきありがとうございます!
ベースの colMeans または Rcpp バージョンよりもはるかに遅く実行するために、おそらく RcppArmadillo コードで何か馬鹿なことをしているのだろうか?
colMeansRcppArmadillo <- cxxfunction(signature(X_="integer"),
plugin="RcppArmadillo",
body='
arma::mat X = Rcpp::as<arma::mat > (X_);
arma::rowvec MD= arma::mean(X, 0);
return wrap(MD);
')
そしてベンチマークは…
(mb = microbenchmark(
+ colMeans(fqSmallMatrix),
+ colMeansRcpp(fqSmallMatrix),
+ colMeansRcppArmadillo(fqSmallMatrix),
+ times=50))
Unit: milliseconds
expr min lq median uq max neval
colMeans(fqSmallMatrix) 10.620919 10.63289 10.640819 10.648882 10.907145 50
colMeansRcpp(fqSmallMatrix) 2.649038 2.66832 2.676709 2.700839 2.841012 50
colMeansRcppArmadillo(fqSmallMatrix) 25.687067 26.23488 33.168589 33.792489 113.832495 50