2013-07-01 3 views
9

Sono confuso.Come accedere agli elementi di un vettore in un elenco Rcpp ::

Il seguente compilare e funziona bene:

#include <Rcpp.h> 
using namespace Rcpp; 
// [[Rcpp::export]] 
List test(){ 
    List l; 
    IntegerVector v(5, NA_INTEGER); 
    l.push_back(v); 
    return l; 
} 

In R:

R) test() 
[[1]] 
[1] NA NA NA NA NA 

Ma quando provo a impostare il IntegerVector nella lista:

// [[Rcpp::export]] 
List test(){ 
    List l; 
    IntegerVector v(5, NA_INTEGER); 
    l.push_back(v); 
    l[0][1] = 1; 
    return l; 
} 

non lo fa compila:

test.cpp:121:8: error: invalid use of incomplete type 'struct SEXPREC' 
C:/PROGRA~1/R/R-30~1.0/include/Rinternals.h:393:16: error: forward declaration of 'struct SEXPREC' 

risposta

15

È a causa di questa linea:

l[0][1] = 1; 

Il compilatore non ha idea che l è una lista di vettori interi. In sostanza l[0] ti dà un SEXP (il tipo generico per tutti gli oggetti R), e SEXP è un puntatore opaco a SEXPREC di cui non abbiamo accesso alla definizione (quindi opaco). Quindi quando fai il [1], provi a ottenere il secondo SEXPREC e quindi l'opacità lo rende impossibile, e non è quello che volevi comunque.

bisogna essere specifico che si sta estraendo un IntegerVector, in modo da poter fare qualcosa di simile:

as<IntegerVector>(l[0])[1] = 1; 

o

v[1] = 1 ; 

o

IntegerVector x = l[0] ; x[1] = 1 ; 

Tutti questi le opzioni funzionano sulla stessa struttura dati sottostante.

In alternativa, se si desidera realmente la sintassi l[0][1], è possibile definire la propria struttura dati che esprime "elenco di vettori interi". Ecco uno schizzo:

template <class T> 
class ListOf { 
public: 

    ListOf(List data_) : data(data_){} 

    T operator[](int i){ 
     return as<T>(data[i]) ; 
    } 
    operator List(){ return data ; } 

private: 
    List data ; 
} ; 

Quale è possibile utilizzare, ad es. in questo modo:

// [[Rcpp::export]] 
List test2(){ 
    ListOf<IntegerVector> l = List::create(IntegerVector(5, NA_INTEGER)) ; 
    l[0][1] = 1 ; 
    return l; 
} 

Si noti inoltre che l'utilizzo di .push_back su Rcpp vettori (compresi gli elenchi) richiede una copia completa dei dati della lista, che può causare rallentare. Usa le funzioni di ridimensionamento solo quando non hai una scelta.

+1

Parfait! grazie mille per la tua risposta ! – statquant

+0

Un'altra domanda Romain, posso creare un 'Rcpp :: List' contenente' n' (dire 3) 'std :: vector ' o 'Rcpp :: IntegerVector' con un solo liner (può essere un' ctor'), come 'IntegerVector v (3, NA_INTEGER); Rcpp :: List test (3, v) ' – statquant

+0

Funziona così:' Lista l (3, IntegerVector (3, NA_INTEGER)) ', ma c'è un errore di battitura in uno dei nostri file (' fill__dispatch' è scritto come 'fill_dispatch' (un carattere di sottolineatura)), quindi fallisce. L'ho risolto localmente e mi impegnerò abbastanza presto. –