问题
I have been trying to implement apply function in Rcpp so far the code looks like this
//[[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);
}
but i'm getting an error "cannot convert SEXP to double in assignment" in line 6 and 11. Is there any way to convert the value returned by an arbitrary function to double? also is there a sugar function for the apply function.
回答1:
There is no sugar function for apply
. The easiest way of doing what you want is to call as<double>
, i.e.:
output[i]=as<double>(f(x(i,_)));
You could also embed this in a type that would call as
for you, something like:
template <typename T>
class F {
public:
F( SEXP f_) : f(f_){}
inline T operator()(NumericVector x){
return as<T>(f(x)) ;
}
private:
Function f ;
} ;
so that you could do:
// [[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 ;
}
}
The F
template from above assumes that the function takes a NumericVector
and returns something that can be converted to a double
. You could also embed type information about both inputs and outputs. Something like this (expressed in 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 ;
} ;
Then the signature would become:
// [[Rcpp::export]]
NumericVector apply_cpp(NumericMatrix x,int dim,F<double,NumericVector> f){
回答2:
The answers are, in order, "yes" and "yes", and you may want to read the "Rcpp Introduction" which contains the following lapply()
example:
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")
This was written for inline rather than Rcpp Attributes because that is how we rolled back in the day. We have more apply-alike functions in other examples and unit tests...
You have not specified what arguments your function f()
takes and returns which makes fixing your question a little trickier.
来源:https://stackoverflow.com/questions/23630538/implementing-apply-function-in-rcpp