orizon
orizon

Reputation: 3239

I don't understand this behaviour in Rcpp

I would like to access the value of the second unique element in an integer vector using Rcpp, but instead I get a vector of zeros that is equal in length to the value of the second item in the integer vector. What am I doing wrong?

require(Rcpp)
cppFunction("NumericVector test(IntegerVector labelling1) {
  IntegerVector lvls = unique(labelling1);
  return(lvls[1]);
}")

  test(1:5)
 #[1] 0 0

Upvotes: 0

Views: 253

Answers (2)

Kevin Ushey
Kevin Ushey

Reputation: 21315

There is actually a separate issue here: you are trying to construct a NumericVector from an int, and Rcpp does the following:

  1. The integer value 2 is being returned by your function,
  2. A NumericVector is constructed as NumericVector(2); ie, a NumericVector with length 2.

If what you really want is an IntegerVector representing the value at that index, you must write:

IntegerVector test(IntegerVector labelling1) {
  IntegerVector lvls = unique(labelling1);
  return IntegerVector::create(lvls[1]);
}

Or you could also do, using Rcpp attributes (which handles conversion from int to IntegerVector automatically for you):

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
int test(IntegerVector labelling1) {
  IntegerVector lvls = unique(labelling1);
  return lvls[1];
}

/*** R
test(1:5)
*/

Upvotes: 2

Roland
Roland

Reputation: 132969

Subsetting sugar expects an IntegerVector as index (http://gallery.rcpp.org/articles/subsetting/). If you want to mimic R's unique function you need some additional changes:

cppFunction("IntegerVector  test(IntegerVector labelling1, int i) {
              // get sorted unique values
              IntegerVector lvls = sort_unique(labelling1);
              // get unique values in order of occurence 
              IntegerVector lvls1 = lvls[match(lvls, labelling1) - 1];
              return(lvls1[IntegerVector::create(i - 1)]);}")

test(c(5:1, 1L), 2)
#[1] 4

Upvotes: 1

Related Questions