在Rcpp中实现应用功能

时间:2014-05-13 11:53:41

标签: c++ rcpp syntactic-sugar

到目前为止,我一直在尝试在Rcpp中实现apply函数,代码看起来像这样

//[[Rcpp::export]]
NumericVector apply(NumericMatrix x,int dim,Function f){
  NumericVector output;
  if(dim==1){
   for(int i=0;i<x.nrow();i++){
     output[i]=f(x(i,_));
   }    
  }
  else if(dim==2){
   for(int i=0;i<x.ncol();i++){
     output[i]=f(x(_,i));
   }
  }
  return(output);
} 

但是我在第6行和第11行中收到错误“无法将SEXP转换为赋值转换”。有没有办法将任意函数返回的值转换为double? apply函数也有一个糖函数。

2 个答案:

答案 0 :(得分:4)

apply没有糖功能。做你想做的最简单的方法就是打电话给as<double>,即:

output[i]=as<double>(f(x(i,_)));

您还可以将此类型嵌入到为您调用as的类型中,例如:

template <typename T>
class F {
public: 
  F( SEXP f_) : f(f_){}

  inline T operator()(NumericVector x){
    return as<T>(f(x)) ;  
  }

private:
  Function f ;
} ;

这样你就可以:

// [[Rcpp::export]]
NumericVector apply_cpp(NumericMatrix x,int dim,F<double> f){
  if(dim==1){
    NumericVector output(x.nrow());
    for(int i=0;i<x.nrow();i++){
      output[i]=f(x(i,_));
    } 
    return output ;
  }
  else {
    NumericVector output(x.ncol());

    for(int i=0;i<x.ncol();i++){
      output[i]=f(x(_,i));
    }  
    return output ;
  }
} 

上面的F模板假设该函数采用NumericVector并返回可转换为double的内容。您还可以嵌入有关输入和输出的类型信息。像这样的东西(用C ++ 11表示):

template <typename T, typename... Args>
class F {
public: 
  F( SEXP f_) : f(f_){}

  inline T operator()(Args... args){
    return as<T>(f(args...)) ;  
  }

private:
  Function f ;
} ;

然后签名将成为:

// [[Rcpp::export]]
NumericVector apply_cpp(NumericMatrix x,int dim,F<double,NumericVector> f){

答案 1 :(得分:3)

答案依次为“是”和“是”,您可能需要阅读包含以下lapply()示例的“Rcpp简介”:

R> src <- '
+   Rcpp::List input(data);
+   Rcpp::Function f(fun);
+   Rcpp::List output(input.size());
+   std::transform(input.begin(), input.end(), output.begin(), f);
+   output.names() = input.names();
+   return output;
+   '
R> cpp_lapply <- cxxfunction(signature(data = "list", fun = "function"),
+    src, plugin = "Rcpp")

这是为内联而不是Rcpp属性编写的,因为这是我们在当天回滚的方式。我们在其他示例和单元测试中有更多类似的功能......

你没有指定函数f()采用的参数和返回值,这使得修复问题变得有点棘手。