RcppArmadillo使用rnorm()填充矩阵列的能力

时间:2014-05-05 20:58:40

标签: r rcpp

我试图实现一个模仿mvtnorm的rmvnorm函数输出的rmvrnorm函数。

这是我到目前为止所做的:

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

using namespace Rcpp;

// [[Rcpp::export]]
arma::mat rmvrnorm_arma(int n, arma::vec mu, arma::mat sigma) {
   int ncols = sigma.n_cols;
   // works with rng?
   arma::mat Y(n,ncols);
   RNGScope scope;
   for(int i = 0; i<ncols; i++){
     // Fill a column using rnorm(n, mean = 0, sd = 1)
     Y.col(i) = rnorm(n);
   }

   return arma::repmat(mu, 1, n).t() + Y * arma::chol(sigma);
}

我在循环中的行上收到错误。

具体来说,行:

         Y.col(i) = rnorm(n);

它声明:

  

&#34; rmvrnorm_arma.cpp:16:15:错误:没有可行的重载&#39; =&#39;

     
 Y.col(i) = rnorm(n);
 ~~~~~~~~ ^ ~~~~~~~~ "
  

我知道arma有arma :: randn()并且我可能会受到性能影响,但是,使用randn()会否定R的RNG范围。我希望能够将此函数的输出与rmvnorm()进行比较。

2 个答案:

答案 0 :(得分:4)

您需要帮助编译器:使用asRcpp::NumericVector对象的默认rnorm对象转换为arma::vec对象。

Y.col(i) = as<arma::vec>(rnorm(n));

答案 1 :(得分:4)

鉴于rnorm(int)如何工作,即它使用the NormGenerator__mean0__sd1类创建NumericVector,这只是::norm_rand函数的包装,你可以使用更多的STL-喜欢:

std::generate( Y.col(i).begin(), Y.col(i).end(), ::norm_rand ) ;

或者您可以直接在整个矩阵上使用std::generate

std::generate( Y.begin(), Y.end(), ::norm_rand ) ;

这会跳过临时NumericVectorarma::vec的创建(和内存分配)。如果您需要rnorm中的其他参数,通过查看各种generators are implemented in Rcpp的方式,您可以轻松地从此方法中获得。

你也可以在armadillo中使用imbue方法:

Y.imbue( norm_rand ) ;