Преобразование std :: vector в матрицу Rcpp

Это связано с преобразованием Rcpp. В. Я хочу преобразовать длинный std :: vector в объект матрицы Rcpp, но хочу знать, существует ли простой формат преобразования. Естественно, вы можете перебрать каждый элемент и заполнить пустую матрицу Rcpp, но это кажется подверженным ошибкам и, возможно, ненужным, если возможен более удобный подход.

Причина, по которой я спрашиваю, заключается в том, что я хотел бы использовать OpenMP в некотором существующем коде C ++, но сохранение элемента в объекте матрицы Rcpp непосредственно в цикле OpenMP не работает должным образом (тогда как загрузка объекта std :: vector и преобразование к матрице после завершения цикла OpenMP кажется достойным подходом к проблеме).

Любая помощь будет принята с благодарностью!


person philchalmers    schedule 08.11.2013    source источник


Ответы (2)


Вы выбрали хороший подход. В контексте OpenMP вы должны держаться подальше от однопоточного R. Так что std::vector - это хорошо.

И да, у нас есть конструкторы от std::vector до Rcpp::NumericVector и Rcpp::NumericMatrix (который, в конце концов, просто вектор с атрибутом размеров), а также варианты Rcoo:Integer*, а также обычные конвертеры as<> и wrap.

В модульных тестах Rcpp, примерах Rcpp и, конечно же, должно быть много примеров на сайте галереи Rcpp.

Изменить: Вот слишком простой пример:

 R> cppFunction('NumericVector phil(int n) { std::vector<double> x(n);
 +              return wrap(x); }') 
 R> phil(4)  
 [1] 0 0 0 0    
 R>    
person Dirk Eddelbuettel    schedule 08.11.2013
comment
Отлично, большое спасибо, Дирк. Я не видел ничего в галерее Rcpp или в примерах, поставляемых с пакетом, но, возможно, я просто недостаточно внимательно смотрел ... - person philchalmers; 08.11.2013
comment
Понятно. Да, я понимаю, что std :: vector легко конвертируются в векторы Rcpp, но меня больше интересовал наиболее оптимальный способ заполнения NumericMatrix с учетом std :: vector и известных размеров (я думаю, что-то вроде NumericMatrix ret = vector2NumericMatrix(x, n, m);, где n и m - количество строк и столбцов. Легко написать функцию для этого, конечно, но мне было больше интересно, было ли что-то подобное уже сделано. Спасибо! И извините, если я приставал к вам по тривиальным вещам :) - person philchalmers; 08.11.2013
comment
Вы также можете рассмотреть RcppArmadillo, который, как библиотека линейной алгебры / матриц, имеет множество подмножеств, объединения, комбинирования, ... операторов. Вероятно, это был бы мой выбор. Возможно, нам не хватает одного или двух конвертеров. Взносы приветствуются. - person Dirk Eddelbuettel; 08.11.2013

Чтобы расширить ответ Дирка; Матрицы R на самом деле просто векторы с установленным атрибутом dim

> x <- 1
> y <- as.matrix(x)
> .Internal( inspect(x) )
@7f81a6c80568 14 REALSXP g0c1 [MARK,NAM(2)] (len=1, tl=0) 1 ## data
> .Internal( inspect(y) )
@7f81a3ea86c8 14 REALSXP g0c1 [NAM(2),ATT] (len=1, tl=0) 1 ## data
ATTRIB:
  @7f81a3e68e08 02 LISTSXP g0c0 [] 
    TAG: @7f81a30013f8 01 SYMSXP g1c0 [MARK,LCK,gp=0x4000] "dim" (has value) 
    @7f81a3ea8668 13 INTSXP g0c1 [NAM(2)] (len=2, tl=0) 1,1

Обратите внимание на то, что компонент «данные» x и y - это всего лишь REALSXP, но у вас есть этот дополнительный dim компонент в матрице. Используя это, мы можем легко преобразовать NumericVector в матрицу в Rcpp.

(Примечание: в приведенном ниже примере я использую SEXP в атрибутах, чтобы преобразование между типами было явным):

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
SEXP vec_to_mat(SEXP x_) {
  std::vector<double> x = as< std::vector<double> >(x_);
  /* ... do something with x ... */
  NumericVector output = wrap(x);
  output.attr("dim") = Dimension(x.size(), 1);
  return output;
}

/*** R
m <- c(1, 2, 3)
vec_to_mat(m)
*/

дает мне

> m <- c(1, 2, 3)

> vec_to_mat(m)
     [,1]
[1,]    1
[2,]    2
[3,]    3

Итак, вы можете использовать класс Dimension и назначить его атрибуту dim вектора, чтобы создать матрицу «вручную» в Rcpp.

person Kevin Ushey    schedule 08.11.2013
comment
Имеет смысл. Спасибо! - person philchalmers; 09.11.2013