分配 n NumericMatrix 的 Rcpp 列表

dr_*_*nch 2 r rcpp

有没有办法分配一个长度为 n 的 Rcpp List,其中 List 的每个元素都会填充一个 NumericMatrix,但是每个 NumericMatrix 的大小可以改变?

我有一个使用 std::list 和 push_back() 执行此操作的想法,但列表的大小可能非常大,我想避免从函数返回时创建列表的额外副本的开销。

下面的 R 代码给出了我希望做什么的想法:

myvec = function(n) {
  x = vector("list", n)
  for (i in seq_len(n)) {
    nc = sample(1:3, 1)
    nr = sample(1:3, 1)
    x[[i]] = matrix(rbinom(nc * nr, size = 1, prob = 0.5),
                    nrow = nr, ncol = nc)
  }
  x
}
Run Code Online (Sandbox Code Playgroud)

这可能会导致类似的结果:

> myvec(2)
[[1]]
     [,1]
[1,]    0
[2,]    1

[[2]]
     [,1] [,2] [,3]
[1,]    0    1    0
[2,]    0    1    1
Run Code Online (Sandbox Code Playgroud)

更新:根据@Dirk 和@Ralf 的评论,我创建了基于 Rcpp::List 和 std::list 的函数,并在末尾使用了换行符。速度比较似乎并不支持一个版本而不是另一个版本,但也许我没有意识到效率低下。

src = '
#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::List myvec(int n) {
  Rcpp::RNGScope rngScope;
  Rcpp::List x(n);
  // Rcpp::IntegerVector choices = {1, 2 ,3};
  Rcpp::IntegerVector choices = Rcpp::seq_len(50);
  for (int i = 0; i < n; ++i) {
    int nc = Rcpp::sample(choices, 1).at(0);
    int nr = Rcpp::sample(choices, 1).at(0);
    Rcpp::NumericVector entries = Rcpp::rbinom(nc * nr, 1, 0.5);
    x(i) = Rcpp::NumericMatrix(nc, nr, entries.begin());
  }
  return x;
}

// [[Rcpp::export]]
Rcpp::List myvec2(int n) {
  Rcpp::RNGScope scope;
  std::list< Rcpp::NumericMatrix > x;
  // Rcpp::IntegerVector choices = {1, 2 ,3};
  Rcpp::IntegerVector choices = Rcpp::seq_len(50);
  for (int i = 0; i < n; ++i) {
    int nc = Rcpp::sample(choices, 1).at(0);
    int nr = Rcpp::sample(choices, 1).at(0);
    Rcpp::NumericVector entries = Rcpp::rbinom(nc * nr, 1, 0.5);
    x.push_back( Rcpp::NumericMatrix(nc, nr, entries.begin()));
  }
  return Rcpp::wrap(x);
}
'
sourceCpp(code = src)

Run Code Online (Sandbox Code Playgroud)

我的计算机上的结果基准是:

> library(microbenchmark)
> rcpp_list = function() {
+   set.seed(10);myvec(105)
+ }
> std_list = function() {
+   set.seed(10);myvec2(105)
+ }
> microbenchmark(rcpp_list(), std_list(), times = 1000)
Unit: milliseconds
        expr    min      lq     mean  median      uq
 rcpp_list() 1.8901 1.92535 2.205286 1.96640 2.22380
  std_list() 1.9164 1.95570 2.224941 2.00555 2.32315
    max neval cld
 7.1569  1000   a
 7.1194  1000   a
Run Code Online (Sandbox Code Playgroud)

Dir*_*tel 5

Rcpp 对象是 R 对象的基本问题控制了我的 R 的内存管理,其中调整大小很昂贵:完整副本。

因此,当我有与您类似的任务,其中大小可能会改变或未知时,我经常使用不同的数据结构——STL 为我们提供了很多——并且只return在最后的步骤中转换为 R(cpp) 。

这里的细节是魔鬼(一如既往)。简介、实验、...

编辑:从狭义的“我们可以返回具有不同大小的 NumericMatrix 对象列表”,答案当然是我们可以, 因为这就是 List 对象所做的。您也可以插入其他类型。