我试图实现一个模仿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()进行比较。
答案 0 :(得分:4)
您需要帮助编译器:使用as
将Rcpp::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 ) ;
这会跳过临时NumericVector
和arma::vec
的创建(和内存分配)。如果您需要rnorm
中的其他参数,通过查看各种generators are implemented in Rcpp的方式,您可以轻松地从此方法中获得。
你也可以在armadillo中使用imbue
方法:
Y.imbue( norm_rand ) ;