我一直在测试 Rcpp 和 RcppArmadillo 来计算大矩阵的汇总统计数据。这比大约 400 万行、45 列的基本 R colMeans 或犰狳要快得多(快 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);
')
我真的很想计算中位数,也许还有其他分位数用于绘图 - 因为它需要一种排序,所以它更需要 C++ 外包。犰狳似乎有点慢,所以我想对与上面类似的代码进行就地排序,但我只是无法正确理解语法......这就是我正在尝试的......
# 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 糖和标准 C++ 的混合物来表达“对列进行排序”。抱歉,我可以看出我在做什么是错误的,但是关于正确语法的提示会很可爱。
ps 我是对的,我需要这样做 clone() 所以我不更改 R 对象吗?
编辑 我添加了 RcppArmadillo 代码和基准比较来解决下面的答案/评论。该基准仅针对 50k 行进行快速回复,但我记得它与更多类似。我知道你是 Rcpp 作者.. 非常感谢你的时间!
出现的想法是,也许我正在对 RcppArmadillo 代码做一些愚蠢的事情,以使其运行速度比基本 colMeans 或 Rcpp 版本慢得多?
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