Rcpp在从R包'numDeriv'导入'hessian'时出现问题

3
我正在尝试构建一个包,其中使用了来自“numDeriv”包的函数“hessian”。然而,当我构建包并运行代码时,会出现以下错误:
无法将对象转换为环境:[类型=字符; 目标=ENVSXP]。
以下是简化后的Rcpp示例代码。
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
#include <stdio.h> 
#include<armadillo>
using namespace Rcpp;
using namespace std;


double testfunc(double X){

  return pow(X+1,2);

}


double hessian_rcpp(double X){

  Rcpp::Environment numDeriv("package:numDeriv");
  Rcpp::Function hessian = numDeriv["hessian"];

  Rcpp::List hessian_results = hessian(
  Rcpp::_["func"] = Rcpp::InternalFunction(testfunc), 
    Rcpp::_["x"] = X);

  arma::vec out = Rcpp::as<arma::vec>(hessian_results[0]);

  return out[0];
}

// [[Rcpp::export]]
double returnhess(double X){

  double out = hessian_rcpp(X);

  return out;

}

在构建软件包后,运行以下 R 代码会导致错误。

library(test)
returnhess(X=3)
Error in returnhess(X = 3) : 
Cannot convert object to an environment: [type=character; target=ENVSXP].

我的命名空间是

useDynLib(test, .registration=TRUE)
importFrom(Rcpp, evalCpp)
exportPattern("^[[:alpha:]]+")

我的描述是

Package: test
Type: Package
Title: What the Package Does (Title Case)
Version: 0.1.0
Author: Who wrote it
Maintainer: The package maintainer <yourself@somewhere.net>
Description: More about what it does (maybe more than one line) Use four spaces when indenting paragraphs within the Description.
License: What license is it under?
Imports: Rcpp, RcppArmadillo, numDeriv
LinkingTo: Rcpp, RcppArmadillo, numDeriv
Encoding: UTF-8
LazyData: true

我的R版本是3.5.1,RStudio版本是1.1.456,Rcpp版本是0.12.19,RcppArmadillo版本是0.9.100.5.0,numDeriv版本是2016.8.1。我的操作系统是Windows 10。
我成功地从R包“stats”中导入了“optimize”,使用了类似的方法。以下是简化的示例代码。
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
#include <stdio.h> 
#include<armadillo>
using namespace Rcpp;
using namespace std;

  double testfunc(double X){

  return pow(X+1,2);

}

double optim_rcpp(){

  Rcpp::Environment stats("package:stats");
  Rcpp::Function optimize = stats["optimize"];

  Rcpp::List opt_results = optimize(
  Rcpp::_["f"] = Rcpp::InternalFunction(testfunc), 
  Rcpp::_["lower"] = -10, 
  Rcpp::_["upper"] =  10);

  arma::vec out = Rcpp::as<arma::vec>(opt_results[0]);

  return out[0];
}

// [[Rcpp::export]]
double returnoptim(){

  double out = optim_rcpp();

  return out;

}

与上述相同的NAMESPACE和DESCRIPTION

然后运行以下R代码就可以了

returnoptim()
[1] -1

1
我忘了提到,如果在运行returnhess之前运行library(numDeriv)或require(numDeriv),它就可以工作。但是,如果它在打包的R函数中,当运行devtools::check()时会出现警告。最终它确实在其中。如果我尝试使用requireNamespace(numDeriv),它将无法工作。 - mike
1
你尝试过之前问题的类比吗?https://stackoverflow.com/q/52952775/8416610 - Ralf Stubner
@RalfStubner,我试过了。但是没有起作用:(我的终极目标是将这个包放到CRAN上。 我试图避免“require”解决方法,因为那会导致警告并可能导致我的软件包不被接受。 - mike
2个回答

4
作为解决方案,您可以添加:
 Depends:numDeriv

numDeriv包与您的软件包一起加载,以确保您的DESCRIPTION中有所提及。

顺便说一句:在软件包中我会避免使用using namespace Rcpp;。我从不使用using namespace std;。当使用RcppArmadillo时,不需要使用#include <stdio.h>#include<armadillo>是不必要的。


成功了,谢谢!我也感谢其他的提示。我之前加入了 #include <stdio.h> 是因为在构建包时出现了“退出状态 15”的错误。但现在这个错误已经消失了。 - mike

0
除了@RalfStubner的回答之外,我想指出以下内容。Rcpp::Environment命名空间有一个函数namespace_env("the_package_name")。 这为您提供了与R的方法packagename::package_functionX(...)相同的功能。结合DESCRIPTION文件中的Depends或Imports,您就可以安全地进行操作。 基于此,您可以按照以下步骤进行:
#include <iostream>
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>


double testfunc(double X){
  
  return std::pow(X+1,2);
  
}

double optim_rcpp(){
  
  Rcpp::Environment stats =  Rcpp::Environment::namespace_env("stats");
  Rcpp::Function optimize = stats["optimize"];
  
  Rcpp::List opt_results = optimize(
    Rcpp::_["f"] = Rcpp::InternalFunction(testfunc), 
    Rcpp::_["lower"] = -10, 
    Rcpp::_["upper"] =  10);
  
  arma::vec out = Rcpp::as<arma::vec>(opt_results[0]);
  
  return out[0];
}

// [[Rcpp::export]]
double returnoptim(){
  
  return optim_rcpp();
}

/*** R
 returnoptim() # -1
*/

回答@mike的问题,你也可以这样做:

#include <iostream>
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>


double testfunc(double X){
  
  return std::pow(X+1,2);
  
}

double hessian_rcpp(double X){
  
  Rcpp::Environment numDeriv =  Rcpp::Environment::namespace_env("numDeriv");
  Rcpp::Function hessian = numDeriv["hessian"];
  
  Rcpp::List hessian_results = hessian(
    Rcpp::_["func"] = Rcpp::InternalFunction(testfunc), 
    Rcpp::_["x"] = X);
  
  arma::vec out = Rcpp::as<arma::vec>(hessian_results[0]);
  
  return out[0];
}


// [[Rcpp::export]]
double returnhess(double X){
  
  return hessian_rcpp(X);
}

/*** R
 returnhess(X=3) # 2
*/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接