Создание большого списка (больших) векторов с помощью Rcpp - PullRequest
0 голосов
/ 11 ноября 2018

Ввод моей функции состоит из двух матриц mat1 и mat2 и количества перестановок B. И mat1, и mat2 имеют m столбцов, но различное количество строк.

Функция сначала переставляет строки обеих матриц (при сохранении информации о столбцах). Затем он выполняет некоторую операцию, которая сравнивает столбцы переставленных версий mat1 и mat2.

Ниже приведен пример моей функции permute_data. Функция сравнения CompareMatCols() выводит вектор длины m.

Вопрос Каков наилучший способ инициализации моего объекта списка вывода? Я видел несколько постов, указывающих на ограничения push_back. И B и m будут порядка ~ 10000, поэтому эффективный способ будет идеальным.

#include <Rcpp.h>
#include <math.h>
//#include <random> //for std::shuffle

using namespace std;
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector ColMax(NumericMatrix X) {
  NumericVector out = no_init(X.cols());
  for(int j = 0; j < X.cols(); ++j) {
      double omax = X(0,j);
    for(int i = 0; i < X.rows(); ++i){
      omax = std::max(X(i,j),omax);
    }
    out[j] = omax;
  }
  return out;
}

// [[Rcpp::export]]
NumericVector vecmin(NumericVector vec1, NumericVector vec2) {
  int n = vec1.size();
  if(n != vec2.size()) return 0;
  else {
    NumericVector out = no_init(n);
    for(int i = 0; i < n; i++) {
      out[i] = std::min(vec1[i], vec2[i]);
    }
    return out;
  }
}

// [[Rcpp::export]]
List permute_data(NumericMatrix mat1,NumericMatrix mat2,int B) {

  List out(B); // How to initialize this???, Will be large ~10000 elements
  int N1 = mat1.rows();
  int N2 = mat2.rows();
  int m = mat1.cols(); //Will be large ~10000 elements

  // Row labels to be permuted
  IntegerVector permindx = seq(0,N1+N2-1);
  NumericMatrix M1 = no_init_matrix(N1,m);
  NumericMatrix M2 = no_init_matrix(N2,m);

  for(int b = 0; b<B; ++b){
    // Permute the N1+N2 rows
   /*std::random_device rng;
   std::mt19937 urng(rng()); //uniform rng
   std::shuffle(permindx.begin(),permindx.end(),urng);*/
    permindx = sample(permindx,N1+N2); //Use Rcpp's function to work with R's RNG
    for(int j=0; j<m; ++j){
        // Pick out first N1 elements of permindx
        for(int i=0; i<N1; ++i){
          if(permindx[i]>=N1){ //Check that shuffled index is in bounds
            M1(i,j) = mat2(permindx[i],j);
          } else{
            M1(i,j) = mat1(permindx[i],j);
          }
        }
        // Pick out last N2 elements of permindx
        for(int k=0; k<N2; ++k){
          if(permindx[k+N1]<N1){ //Check that shuffled index is in bounds
            M2(k,j) = mat1(permindx[k+N1],j);
          } else{
            M2(k,j) = mat2(permindx[k+N1],j);
          }
        }
    }
    out[b] = vecmin(ColMax(M1),ColMax(M2)); //a vector of length m
  }
  return(out);
}

/***R
set.seed(1)
X = matrix(rnorm(3*5),ncol=5)
Y = matrix(rnorm(5*5),ncol=5)
B = 5
res = permute_data(X,Y,B)
*/

Редактировать: Добавлены строки в адрес точки @ Duckmayr. Изменить 2: По предложению Дирка, я включил минимально полный проверяемый пример.

1 Ответ

0 голосов
/ 14 ноября 2018

В конце концов, решение, которое я выбрал, - это то, что было показано выше:

// [[Rcpp::export]]
List permute_data(NumericMatrix mat1,NumericMatrix mat2,int B) {

  List out(B); // Will be large ~5000 elements
  int N1 = mat1.rows();
  int N2 = mat2.rows();
  int m = mat1.cols(); //Will be large ~10000 elements

  // Row labels to be permuted
  IntegerVector permindx = seq(0,N1+N2-1);
  NumericMatrix M1 = no_init_matrix(N1,m);
  NumericMatrix M2 = no_init_matrix(N2,m);

  for(int b = 0; b<B; ++b){
    // Permute the N1+N2 rows
    permindx = sample(permindx,N1+N2); //Use Rcpp's function to work with R's RNG
    for(int j=0; j<m; ++j){
        // Pick out first N1 elements of permindx
        for(int i=0; i<N1; ++i){
          if(permindx[i]>=N1){ //Check that shuffled index is in bounds
            M1(i,j) = mat2(permindx[i],j);
          } else{
            M1(i,j) = mat1(permindx[i],j);
          }
        }
        // Pick out last N2 elements of permindx
        for(int k=0; k<N2; ++k){
          if(permindx[k+N1]<N1){ //Check that shuffled index is in bounds
            M2(k,j) = mat1(permindx[k+N1],j);
          } else{
            M2(k,j) = mat2(permindx[k+N1],j);
          }
        }
    }
    out[b] = vecmin(ColMax(M1),ColMax(M2)); //a vector of length m
  }
  return(out);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...