Ordering Permutation in Rcpp i.e. base::order()

前端 未结 3 1480
不知归路
不知归路 2020-12-14 05:26

I have a ton of code using the base::order() command and I am really too lazy to code around that in rcpp. Since Rcpp only supports sort, but not order, I spent 2 m

3条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-12-14 05:58

    Here's a simple version leveraging Rcpp sugar to implement an order function. We put in a check for duplicates so that we guarantee that things work 'as expected'. (There is also a bug with Rcpp's sort method when there are NAs, so that may want to be checked as well -- this will be fixed by the next release).

    #include 
    using namespace Rcpp;
    
    // [[Rcpp::export]]
    IntegerVector order_(NumericVector x) {
      if (is_true(any(duplicated(x)))) {
        Rf_warning("There are duplicates in 'x'; order not guaranteed to match that of R's base::order");
      }
      NumericVector sorted = clone(x).sort();
      return match(sorted, x);
    }
    
    /*** R
    library(microbenchmark)
    x <- runif(1E5)
    identical( order(x), order_(x) )
    microbenchmark(
      order(x),
      order_(x)
    )
    */
    

    gives me

    > Rcpp::sourceCpp('~/test-order.cpp')
    
    > set.seed(456)
    
    > library(microbenchmark)
    
    > x <- runif(1E5)
    
    > identical( order(x), order_(x) )
    [1] TRUE
    
    > microbenchmark(
    +   order(x),
    +   order_(x)
    + )
    Unit: milliseconds
          expr      min       lq   median       uq      max neval
      order(x) 15.48007 15.69709 15.86823 16.21142 17.22293   100
     order_(x) 10.81169 11.07167 11.40678 11.87135 48.66372   100
    > 
    

    Of course, if you're comfortable with the output not matching R, you can remove the duplicated check -- x[order_(x)] will still be properly sorted; more specifically, all(x[order(x)] == x[order_(x)]) should return TRUE.

提交回复
热议问题