Применение функции к столбцам матрицы с использованием RcppArmadillo работает, но возвращает ошибку при применении к строкам - PullRequest
0 голосов
/ 24 февраля 2019

Я кодировал функцию qSelectMbycol в Rcpp, которая возвращает k-й по величине элемент каждого столбца за O (n) времени.Эта функция работает нормально.Если я пытаюсь сделать то же самое, но работаю со строками вместо столбцов (функция qSelectMbyrow), возвращается ошибка "error: Mat::init(): requested size is not compatible with column vector layout".У кого-нибудь есть мысли, что я делаю не так?Я сохранил этот файл как "qselect.cpp":

// [[Rcpp::depends(RcppArmadillo)]]
#define RCPP_ARMADILLO_RETURN_COLVEC_AS_VECTOR
#include <RcppArmadillo.h>
using namespace arma;

// [[Rcpp::export]]
arma::vec qSelectMbycol(arma::mat& M, const int k) {

  // ARGUMENTS
  // M: matrix for which we want to find the k-th largest elements of each column
  // k: k-th statistic to look up

  arma::mat Y(M.memptr(), M.n_rows, M.n_cols);
  // we apply over columns
  int c = M.n_cols;
  arma::vec out(c);
  int i;
  for (i = 0; i < c; i++) {
      arma::vec y = Y.col(i);
      std::nth_element(y.begin(), y.begin() + k - 1, y.end());
      out(i) = y(k-1); // the k-th largest value of each column
  }

  return out;

}

// [[Rcpp::export]]
arma::vec qSelectMbyrow(arma::mat& M, const int k) {

  // ARGUMENTS
  // M: matrix for which we want to find the k-th largest elements of each row
  // k: k-th statistic to look up

  arma::mat Y(M.memptr(), M.n_rows, M.n_cols);
  // we apply over rows
  int r = M.n_rows;
  arma::vec out(r);
  int i;
  for (i = 0; i < r; i++) {
    arma::vec y = Y.row(i); // this line throws the error "error: Mat::init(): requested size is not compatible with column vector layout"
    std::nth_element(y.begin(), y.begin() + k - 1, y.end());
    out(i) = y(k-1); // should give k-th largest value of each row
  }

  return out;

}

Пример:

n=500
p=100
set.seed(1)
M=matrix(rnorm(n, mean = 100, sd = 1),n,1)
library(Rcpp)
library(RcppArmadillo)
Rcpp::sourceCpp('qselect.cpp')
qSelectMbycol(M,5) # works OK
qSelectMbyrow(M,5) # throws error "error: Mat::init(): requested size is not compatible with column vector layout"

Я также попытался вставить

  typedef std::vector<double> stdvec;

и заменить вектор настройки линииy на

arma::vec y = arma::conv_to<stdvec>::from(Y.row(i)); 

в моей функции qSelectMbyrow, и хотя функция затем запускается, она работает медленно по сравнению с применением над столбцами, а также завершает мой сеанс R, если я запускаю его 100 раз.

1 Ответ

0 голосов
/ 24 февраля 2019

Проблема в том, что arma::vec на самом деле arma::colvec (см. документы ).Таким образом, мы можем решить эту проблему, изменив

arma::vec y = Y.row(i);

(что несовместимо, потому что думает, что вы хотите матрицу с одним столбцом, но вы пытаетесь присвоить ей матрицу с одной строкой) на

arma::rowvec y = Y.row(i);
...