2015-09-15 3 views
6

У меня возникли проблемы с выяснением того, как вернуть RcppArmadillo colvec в качестве стандартного R-вектора. Я надеялся, что смогу набрать as<NumericVector>(wrap(), но я все еще получаю объекты с матрицами R. Вот немного кода, чтобы показать, что я попытался (частично вдохновлен this previous question):Возврат RcppArmadillo vector as R vector

// [[Rcpp::export]]                              
List testthis(NumericVector x) { 
    arma::colvec y = x; 
    arma::vec z = x; 

    return List::create(Rcpp::Named("y1")=y, 
         Rcpp::Named("y2")=wrap(y), 
         Rcpp::Named("y3")=as<NumericVector>(wrap(y)), 
         Rcpp::Named("z1")=z, 
         Rcpp::Named("z2")=arma::trans(z), 
         Rcpp::Named("z3")=as<NumericVector>(wrap(z)) 
        ); 
} 

и если я смотрю на выходе я получаю следующее, которые являются все объекты R матрицы. Могу ли я передать его векторам R?

> testthis(c(1:3)) 
$y1 
    [,1] 
[1,] 1 
[2,] 2 
[3,] 3 

$y2 
    [,1] 
[1,] 1 
[2,] 2 
[3,] 3 

$y3 
    [,1] 
[1,] 1 
[2,] 2 
[3,] 3 

$z1 
    [,1] 
[1,] 1 
[2,] 2 
[3,] 3 

$z2 
    [,1] [,2] [,3] 
[1,] 1 2 3 

$z3 
    [,1] 
[1,] 1 
[2,] 2 
[3,] 3 

ответ

9

Вы можете просто установить атрибут dim в NULL, поскольку матрицы в значительной степени только регулярные векторы с размерным атрибутом. Со стороны C++ это выглядит так:

#include <RcppArmadillo.h> 
// [[Rcpp::depends(RcppArmadillo)]] 

// [[Rcpp::export]] 
Rcpp::List testthis(Rcpp::NumericVector x) { 
    arma::colvec y = x; 
    arma::vec z = x; 

    Rcpp::NumericVector tmp = Rcpp::wrap(y); 
    tmp.attr("dim") = R_NilValue; 

    Rcpp::List result = Rcpp::List::create(
    Rcpp::Named("arma_vec") = y, 
    Rcpp::Named("R_vec") = tmp); 

    return result; 
} 

/*** R 

R> testthis(c(1:3)) 
# $arma_vec 
# [,1] 
# [1,] 1 
# [2,] 2 
# [3,] 3 
# 
# $R_vec 
# [1] 1 2 3 

R> dim(testthis(c(1:3))[[1]]) 
#[1] 3 1 
R> dim(testthis(c(1:3))[[2]]) 
# NULL 

*/ 
+1

Это тоже хорошо - приятно. –

+1

Ответы на вопросы и ответы Нирселла и Дирка помогли мне с моим вопросом. Поскольку они предлагают несколько разные (но действительные) решения, я перевернул монету, чтобы получить ответ. Спасибо, оба! – ekstroem

5

Это «особенность». В какой-то момент очень рано мы решили сохранить размеры, поэтому векторы всегда возвращаются в виде матриц с одной строкой или столбцом. Поскольку этот API был установлен довольно давно, теперь его трудно изменить, поскольку мы сломаем существующий код.

Kudos для проверки всех вышеперечисленных вариантов. Вот еще один, который помогает, перейдя через std::vector<double>:

R> cppFunction("std::vector<double> foo(arma::vec v) { 
+        return as<std::vector<double> >(wrap(v)); }", 
+    depends="RcppArmadillo") 
R> foo(c(5.5,6.6,7.42)) 
[1] 5.50 6.60 7.42 
R> 

Это, вероятно, более эффективно только раздеть размер на стороне R, хотя.

1

Это старый вопрос, но он по-прежнему появляется в первых строках при поиске объекта, поэтому я хотел бы поделиться другим вариантом, который возможен с версии 0.7.960.1.0. Вставьте соответствующий #define перед тем #include и вуаля:

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

// [[Rcpp::export]] 
arma::vec testthis(arma::vec x) { 
    return x+1; 
} 
/*** R 
testthis(1:3) 
*/ 

> testthis(1:3) 
[1] 2 3 4 

Вы можете заменить COLVEC в #define по ROWVEC или ANYVEC в случае необходимости.