Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access elements of a vector in a Rcpp::List

Tags:

r

rcpp

I am puzzled.

The following compile and work fine:

#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

But when I try to set the IntegerVector in the list:

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

It does not compile:

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'
like image 249
statquant Avatar asked Jul 01 '13 15:07

statquant


People also ask

How do I view a specific element in a list in R?

Accessing List Elements. Elements of the list can be accessed by the index of the element in the list. In case of named lists it can also be accessed using the names.

How do you check if a vector is in a list?

To check if a vector exists in a list, we can use %in%, and read the vector as list using list function. For example, if we have a list called LIST and a vector called V then we can check whether V exists in LIST using the command LIST %in% list(V).

What is RCPP function?

Description The 'Rcpp' package provides R functions as well as C++ classes which offer a seamless integration of R and C++. Many R data types and objects can be mapped back and forth to C++ equivalents which facilitates both writing of new code as well as easier integration of third-party libraries.

What is RCPP sugar?

Rcpp Sugar is bases on expression templates and provides some. syntactic sugar facilities direclty in Rcpp. suppressMessages(library(Rcpp)) ## Warning: package Rcpp was built under R version 3.1.3. suppressMessages(library(RcppArmadillo))


1 Answers

It is because of this line:

l[0][1] = 1;

The compiler has no idea that l is a list of integer vectors. In essence l[0] gives you a SEXP (the generic type for all R objects), and SEXP is an opaque pointer to SEXPREC of which we don't have access to te definition (hence opaque). So when you do the [1], you attempt to get the second SEXPREC and so the opacity makes it impossible, and it is not what you wanted anyway.

You have to be specific that you are extracting an IntegerVector, so you can do something like this:

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

or

v[1] = 1 ;

or

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

All of these options work on the same underlying data structure.

Alternatively, if you really wanted the syntax l[0][1] you could define your own data structure expressing "list of integer vectors". Here is a sketch:

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 ;
} ;

Which you can use, e.g. like this:

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

Also note that using .push_back on Rcpp vectors (including lists) requires a complete copy of the list data, which can cause slow you down. Only use resizing functions when you don't have a choice.

like image 158
Romain Francois Avatar answered Sep 26 '22 03:09

Romain Francois