Выделить R cpp Список n NumericMatrix - PullRequest
2 голосов
/ 13 января 2020

Есть ли способ выделить R cpp Список длиной n, где каждый элемент списка будет заполнен 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
}

Это может привести к чему-то вроде:

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

[[2]]
     [,1] [,2] [,3]
[1,]    0    1    0
[2,]    0    1    1

Обновление: основываясь на комментариях @Dirk и @Ralf, я создал функции на основе R cpp :: 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)

В результате на моем компьютере будут получены следующие результаты:

> 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

Ответы [ 2 ]

5 голосов
/ 13 января 2020

* * * * * * * * * * * * * * * * * * * * * * * * * * * * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} может измениться или неизвестно, я часто работаю с различными структурами данных - STL дает нам много - и конвертирую только в R (cpp) на шаге return в конце.

Дьявол в деталях здесь (как всегда). Профиль, эксперимент, ...

Редактировать: И в более узком смысле «можем ли мы вернуть список объектов NumericMatrix с различными размерами» ответ - конечно, мы можем потому что это то, что делают объекты List. Вы также можете вставить другие типы.

2 голосов
/ 13 января 2020

Как сказал Дирк, конечно, можно создать список с матрицами разного размера. Чтобы сделать это немного более конкретным, вот перевод вашей R-функции:

#include <Rcpp.h>
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::export]]
Rcpp::List myvec(int n) {
    Rcpp::List x(n);
    Rcpp::IntegerVector choices = {1, 2 ,3};
    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;
}

/***R
myvec(2)
*/

Основным отличием кода R являются явно названные векторы choices и entries, которые неявны только в код R.

...