2013-07-31 16 views
7

Supponiamo di avere un List in Rcpp, qui chiamato x contenente matrici. Posso estrarre uno degli elementi usando x[0] o qualcosa del genere. Tuttavia, come posso estrarre un elemento specifico di quella matrice? Il mio primo pensiero è stato x[0](0,0) ma non sembra funzionare. Ho provato a utilizzare i segni * ma non funziona.Elemento indice dalla lista in Rcpp

Ecco alcuni esempi di codice che stampa la matrice (mostra matrice può essere facilmente estratto):

library("Rcpp") 

cppFunction(
includes = ' 
NumericMatrix RandMat(int nrow, int ncol) 
{ 
    int N = nrow * ncol; 
    NumericMatrix Res(nrow,ncol); 
    NumericVector Rands = runif(N); 
    for (int i = 0; i < N; i++) 
    { 
    Res[i] = Rands[i]; 
    } 
    return(Res); 
}', 

code = ' 
void foo() 
{ 
    List x; 
    x[0] = RandMat(3,3); 
    Rf_PrintValue(wrap(x[0])); // Prints first matrix in list. 
} 
') 


foo() 

Come potrei cambiare la linea Rf_PrintValue(wrap(x[0])); qui per stampare l'elemento nella prima riga e colonna? Nel codice che voglio usarlo ho bisogno di estrarre questo elemento per fare calcoli.

risposta

7

quelli rapidi: espressione

  1. composto in C++ può mordere, a volte; la magia del modello si intromette. Quindi, basta assegnare dall'oggetto List a qualunque sia l'elemento, ad esempio uno NumericMatrix.

  2. Quindi scegliere dallo NumericMatrix come meglio credi. Abbiamo accesso a righe, colonne, elementi, ...

  3. stampa può essere più facile usando Rcpp::Rcout << anElement ma notare che al momento non in grado di stampare intere matrici o vettori - ma i int o double tipi vanno bene.

Edit:

Ecco un esempio di implementazione.

#include <Rcpp.h> 

// [[Rcpp::export]] 
double sacha(Rcpp::List L) { 
    double sum = 0; 
    for (int i=0; i<L.size(); i++) { 
     Rcpp::NumericMatrix M = L[i]; 
     double topleft = M(0,0); 
     sum += topleft; 
     Rcpp::Rcout << "Element is " << topleft << std::endl; 
    } 
    return sum;  
} 

/*** R 
set.seed(42) 
L <- list(matrix(rnorm(9),3), matrix(1:9,3), matrix(sqrt(1:4),2)) 
sasha(L) 
*/ 

e il suo risultato:

R> Rcpp::sourceCpp('/tmp/sacha.cpp') 

R> set.seed(42) 

R> L <- list(matrix(rnorm(9),3), matrix(1:9,3), matrix(sqrt(1:4),2)) 

R> sacha(L) 
Element is 1.37096 
Element is 1 
Element is 1 
[1] 3.37096 
R> 
5

Devi essere esplicito a un certo punto. La classe List non ha idea dei tipi di elementi che contiene, non sa che è un elenco di matrici.

Dirk ti ha mostrato ciò che facciamo di solito, recupera l'elemento come NumericMatrix ed elabora la matrice.

Ecco un'alternativa che presuppone che tutti gli elementi del tuo elenco abbiano la stessa struttura, utilizzando un nuovo modello di classe: ListOf con sufficiente colla per rendere il codice utente senza problemi. Questo sposta semplicemente in un altro posto l'esplicito.

#include <Rcpp.h> 
using namespace Rcpp ; 

template <typename WHAT> 
class ListOf : public List { 
public: 
    template <typename T> 
    ListOf(const T& x) : List(x){} 

    WHAT operator[](int i){ return as<WHAT>(((List*)this)->operator[](i)) ; } 

} ; 

// [[Rcpp::export]] 
double sacha(ListOf<NumericMatrix> x){ 
    double sum = 0.0 ; 
    for(int i=0; i<x.size(); i++){ 
     sum += x[i](0,0) ;  
    } 
    return sum ; 
} 

/*** R 
    L <- list(matrix(rnorm(9),3), matrix(1:9,3), matrix(sqrt(1:4),2)) 
    sacha(L) 
*/ 

Quando ho sourceCpp questo file, ottengo:

> L <- list(matrix(rnorm(9), 3), matrix(1:9, 3), matrix(sqrt(1:4), 2))  
> sacha(L) 
[1] 1.087057 
Problemi correlati