Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting named numeric vectors in Rcpp

Tags:

r

rcpp

In a function, I want to calculate numeric values, give names to them and return a sorted NumericVector in Rcpp. I can sort the vectors (using this), but the order of the names of the values remains the same.

library(Rcpp)
x <- c(a = 1, b = 5, c = 3)
cppFunction('
NumericVector foo(NumericVector x) {
  std::sort(x.begin(), x.end());
  return(x);
}')
foo(x)
## a b c 
## 1 3 5 

I want the function to return this:

## a c b 
## 1 3 5 

Is it possible? How can I achieve this?

like image 880
HBat Avatar asked Feb 17 '20 01:02

HBat


People also ask

How to sort named vector in R?

To sort a vector alphabetically in R using the sort() function that takes a vector as an argument and returns an alphabetically ordered value for the character vector and ascending order for numeric. Use c() function to create vector. To sort vectors by descending order use decreasing=TRUE param.

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 defines the usual binary arithmetic operators : +, -, *, /. // two numeric vectors of the same size. NumericVector x ; NumericVector y ; // expressions involving two vectors.


1 Answers

Using the tip Dirk gave in his comment, I figured out that names of x is just another vector. So, I searched for sorting a vector using another vector. Using this SO answer I come up with following two solutions:

library(Rcpp)
x = c(a = 1, b = 5, c = 3, d = -3.2)

cppFunction('
NumericVector foo1(NumericVector x) {
 IntegerVector idx = seq_along(x) - 1;
 std::sort(idx.begin(), idx.end(), [&](int i, int j){return x[i] < x[j];});
 return x[idx];
}')

foo1(x)

##    d    a    c    b 
## -3.2  1.0  3.0  5.0 


cppFunction('
NumericVector foo2(NumericVector x) {
 IntegerVector idx = seq_along(x) - 1;
 //// Ordered indices based on x:
 std::sort(idx.begin(), idx.end(), [&](int i, int j){return x[i] < x[j];});
 //// Get the names of x:
 CharacterVector names_of_x = x.names();
 //// y vector is sorted x 
 NumericVector y = x[idx];
 //// Assign sorted names to y vector as names
 y.attr("names") = names_of_x[idx];
 return y;
}')

foo2(x)

##    d    a    c    b 
## -3.2  1.0  3.0  5.0 
like image 143
HBat Avatar answered Sep 24 '22 12:09

HBat