简体   繁体   English

均匀分布矩阵Rcpp

[英]matrix of Uniform distribution Rcpp

I'm trying to create a function, which creates an matrix of size nxm, with entries of the uniform distribution, with the Rcpp package. 我正在尝试使用Rcpp包创建一个函数,该函数创建大小为nxm的矩阵,其中包含均匀分布的条目。 (I'm inexperienced using this package.) (我没有使用此软件包的经验。)

library(Rcpp)
cppFunction('NumericMatrix rngCpp(const int n,const int m) {
   NumericMatrix X(n, m);
             X(_,0) = runif(n);
             return X;
             }')
set.seed(1)
rngCpp(4,5)
          [,1] [,2] [,3] [,4] [,5]
[1,] 0.2655087    0    0    0    0
[2,] 0.3721239    0    0    0    0
[3,] 0.5728534    0    0    0    0
[4,] 0.9082078    0    0    0    0

Expected output 预期产量

set.seed(1)
matrix(runif(4*5), nrow=4, ncol = 5)
          [,1]      [,2]       [,3]      [,4]      [,5]
[1,] 0.2655087 0.2016819 0.62911404 0.6870228 0.7176185
[2,] 0.3721239 0.8983897 0.06178627 0.3841037 0.9919061
[3,] 0.5728534 0.9446753 0.20597457 0.7698414 0.3800352
[4,] 0.9082078 0.6607978 0.17655675 0.4976992 0.7774452

Well with 很好

 X(_,0) = runif(n);

you explicitly only assign to the first column. 明确只分配给第一列。 So just loop over all m column doing the same. 因此,只需循环遍历所有m列即可。

Another (inside-baseball) way is to request a vector of n*m, and then set the dim attributes of (n,m) to make it a matrix. 另一种(内部棒球)方式是请求向量n * m,然后设置(n,m)的dim属性使其成为矩阵。

Related, there is IIRC a constructor that would take that vector and re-dim it. 相关的是,有一个IIRC构造函数,它将采用该向量并对其进行暗化处理。

Edit: And that last approach is the simplest and works like this: 编辑:最后一种方法是最简单的,其工作方式如下:

R> cppFunction('NumericMatrix mu(int n, int m) { 
       NumericVector v = runif(n*m); 
       return NumericMatrix(n, m, v.begin()); }')
R> set.seed(1); mu(4,5)
         [,1]     [,2]      [,3]     [,4]     [,5]
[1,] 0.265509 0.201682 0.6291140 0.687023 0.717619
[2,] 0.372124 0.898390 0.0617863 0.384104 0.991906
[3,] 0.572853 0.944675 0.2059746 0.769841 0.380035
[4,] 0.908208 0.660798 0.1765568 0.497699 0.777445
R> 

Edit 2: Additional variants as F.Privé insists on arguing: 编辑2: F.Privé坚持认为的其他变体:

We can add these two: 我们可以添加以下两个:

// [[Rcpp::export]]
NumericMatrix mu3(int n, int m) { 
  return NumericMatrix(n, m, runif(n*m).begin()); 
}

// [[Rcpp::export]]
NumericMatrix mu4(int n, int m) { 
  NumericVector v = runif(n * m);
  v.attr("dim") = Dimension(n, m);
  return as<NumericMatrix>(v); 
}

and then get 然后得到

R> N <- 1000; M <- 1000

R> microbenchmark::microbenchmark(
+   mu(N, M),
+   mu2(N, M),
+   mu3(N, M),
+   mu4(N, M),
+   rngCpp(N, M)
+ )
Unit: milliseconds
         expr     min      lq    mean  median      uq     max neval
     mu(N, M) 4.77894 4.98485 7.32315 5.18153 5.36468 33.2427   100
    mu2(N, M) 3.99137 4.05308 5.43207 4.36296 4.57510 30.7335   100
    mu3(N, M) 4.73176 5.01524 6.35186 5.17173 5.39541 31.7425   100
    mu4(N, M) 3.99784 4.10052 4.72563 4.41176 4.60303 30.6166   100
 rngCpp(N, M) 5.18726 5.60165 7.53171 5.83892 6.14315 34.5934   100
R> 

In the OP's code, the assignment only happens for the 1st column index ie 0 . 在OP的代码中,分配仅发生在第一列索引即0 We can loop through the column index and assign the uniform distribution values 我们可以遍历列索引并分配均匀分布值

cppFunction('NumericMatrix rngCpp(const int n,const int m) {
   NumericMatrix X(n, m);

             for(int i = 0; i < m; i++){
               X(_,i) = runif(n);
                 }
             return X;
             }')


set.seed(1)
rngCpp(4,5)
#          [,1]      [,2]       [,3]      [,4]      [,5]
#[1,] 0.2655087 0.2016819 0.62911404 0.6870228 0.7176185
#[2,] 0.3721239 0.8983897 0.06178627 0.3841037 0.9919061
#[3,] 0.5728534 0.9446753 0.20597457 0.7698414 0.3800352
#[4,] 0.9082078 0.6607978 0.17655675 0.4976992 0.7774452

Generally, I would use the second idea of Dirk: changing the dimension of a vector so that it becomes a matrix. 通常,我会使用Dirk的第二个想法:更改向量的尺寸,使其成为矩阵。

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector mu2(int n, int m) { 
  NumericVector v = runif(n * m);
  v.attr("dim") = Dimension(n, m);
  return v; 
}

// [[Rcpp::export]]
NumericMatrix mu(int n, int m) { 
  NumericVector v = runif(n*m); 
  return NumericMatrix(n, m, v.begin()); 
}

// [[Rcpp::export]]
NumericMatrix rngCpp(const int n,const int m) {
  NumericMatrix X(n, m);

  for(int i = 0; i < m; i++){
    X(_,i) = runif(n);
  }
  return X;
}

/*** R
set.seed(1); mu(4, 5)
set.seed(1); mu2(4, 5)

N <- 1000; M <- 1000
microbenchmark::microbenchmark(
  mu(N, M),
  mu2(N, M),
  rngCpp(N, M)
)
*/

Microbenchmark: 微基准测试:

Unit: milliseconds
         expr      min        lq     mean    median        uq      max neval cld
     mu(N, M) 7.627591 10.290691 16.05829 10.932174 11.416555 119.2110   100   a
    mu2(N, M) 6.315160  6.590293 12.30125  8.510765  9.368282 117.8750   100   a
 rngCpp(N, M) 8.330158 10.306584 16.14374 10.893767 11.398675 121.4233   100   a

So, mu2 is a bit faster because it doesn't make any copy. 因此, mu2速度更快,因为它不会进行任何复制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM