Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call R functions in Rcpp [duplicate]

Tags:

r

rcpp

I was trying to call the sd(x), which is a R function, in Rcpp. I've seen an example of calling the R function dbate(x) in Rcpp and it works perfectly.

// dens calls the pdf of beta distribution in R
//[[Rcpp::export]]
double dens(double x, double a, double b)
{
    return R::dbeta(x,a,b,false);
}

But when I tired to apply this method to sd(x) as following, it went wrong.

// std calls the sd function in R
//[[Rcpp::export]]
double std(NumericVector x)
{
  return R::sd(x);
}

Does anyone know why this doesn't work?

like image 217
Yuge Hao Avatar asked Jun 24 '16 15:06

Yuge Hao


1 Answers

There are a few issues with your code.

  1. std is related to the C++ Standard Library namespace
    • This is triggering:

      error: redefinition of 'std' as different kind of symbol

  2. The R:: is a namespace that deals with Rmath functions. Other R functions will not be found in within this scope.
  3. To directly call an R function from within C++ you must use Rcpp::Environment and Rcpp::Function as given in the example sd_r_cpp_call().
    • There are many issues with this approach though including but not limited to the loss of speed.
  4. It is ideal to use Rcpp sugar expressions or implement your own method.

With this being said, let's talk code:

#include <Rcpp.h>

//' @title Accessing R's sd function from Rcpp
// [[Rcpp::export]]
double sd_r_cpp_call(const Rcpp::NumericVector& x){

  // Obtain environment containing function
  Rcpp::Environment base("package:stats"); 

  // Make function callable from C++
  Rcpp::Function sd_r = base["sd"];    

  // Call the function and receive its list output
  Rcpp::NumericVector res = sd_r(Rcpp::_["x"] = x,
                                 Rcpp::_["na.rm"]  = true); // example of additional param

  // Return test object in list structure
  return res[0];
}


// std calls the sd function in R
//[[Rcpp::export]]
double sd_sugar(const Rcpp::NumericVector& x){
  return Rcpp::sd(x); // uses Rcpp sugar
}

/***R
x = 1:5
r = sd(x)
v1 = sd_r_cpp_call(x)
v2 = sd_sugar(x)

all.equal(r,v1)
all.equal(r,v2)
*/
like image 137
coatless Avatar answered Oct 17 '22 02:10

coatless