在Rcpp中生成随机Gamma

时间:2015-12-06 04:35:24

标签: r rcpp armadillo

我有矢量形状和比例参数,可以从随机伽玛分布中生成数字。我无法在R中找到方法;

lambda<-matrix(rgamma(p,ak,scale=1/bk),p,1)

所以我试图在循环中生成,似乎我失去了时间,这是使用Rcpp的主要目的。

for(int i = 0; i<p;i++){
lambda(i)=arma::conv_to<double>::from(arma::randg<arma::mat (1,1,arma::distr_param(ak(i),pow(bk(i),-1))));
}

编辑:我模拟了所有3种方法并比较了时间。

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

arma::mat rg(const arma::mat& w,double scale,int num) {
int p = w.n_rows;
arma::mat lambda(num,p,arma::fill::zeros);  


for (int j=0;j<num;j++){
for(int i = 0; i<p;i++){
    lambda(j,i)=arma::conv_to<double>::from(arma::randg<arma::mat>(1,1,arma::distr_param(w(i),scale)));
}
}
return mean(lambda.rows(0,num-1),0);    
}

这些是R代码;

fun<-function(w,sca,num){
p=nrow(w)
lambda=matrix(0,num,p)
for (jj in 1:num){
    for (i in 1:p){
        lambda[jj,i]=rgamma(1,w[i],scale=sca)
    }
}
return(colMeans(lambda))
}

fun2<-function(w,sca,num){
p=nrow(w)
lambda=matrix(0,num,p)
for (jj in 1:num){      
        lambda[jj,]=rgamma(p,w,scale=sca)       
}
return(colMeans(lambda))
}

这是结果;

  a=matrix(c(1,2,3))


  microbenchmark(rg(a,2,100000),fun(a,2,1e5),fun2(a,2,1e5))
  Unit: milliseconds
              expr       min        lq      mean    median        uq       max neval
    rg(a, 2, 1e+05)  891.6197  900.0092  952.3833  915.6609  991.7918 1271.9117   100
    fun(a, 2, 1e+05) 1018.6645 1059.3994 1171.9160 1130.7481 1200.3192 1754.3445   100
   fun2(a, 2, 1e+05)  321.8309  339.2670  373.5317  355.5914  395.1515  604.4365   100

1 个答案:

答案 0 :(得分:1)

您是否理解arma::randg来自Armadillo命名空间?

R::rgamma(标量)或Rcpp::rgamma(矢量化)来自R / Rcpp,参数化为rate = 1/scale - 我在this earlier question of yours向您解释过?< / p>

编辑:这基本上是相同的答案as the last time:对 C ++版rgamma 的简单C ++调用与 R 版本使用&#34; 1 / over&#34;参数化。

R> set.seed(42); stem(rgamma(100, 0.5, 2.0)) # calling from R

  The decimal point is 1 digit(s) to the left of the |

   0 | 00000000000001111111112222222333345566677777778888990111111122345666
   2 | 002257268
   4 | 235788
   6 | 269457
   8 | 70345
  10 | 28
  12 | 1
  14 | 
  16 | 0

R> cppFunction("NumericVector callrgamma(int n, double shape, double scale) { 
+                                        return(rgamma(n, shape, scale)); }")
R> set.seed(42); stem(callrgamma(100, 0.5, 1.0/2.0))  # calling from C++ 

  The decimal point is 1 digit(s) to the left of the |

   0 | 00000000000001111111112222222333345566677777778888990111111122345666
   2 | 002257268
   4 | 235788
   6 | 269457
   8 | 70345
  10 | 28
  12 | 1
  14 | 
  16 | 0

R>