到目前为止,我一直在尝试在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函数也有一个糖函数。
答案 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()
采用的参数和返回值,这使得修复问题变得有点棘手。