【问题标题】:how to add function in R package into rcpp code如何将R包中的函数添加到rcpp代码中
【发布时间】:2018-07-30 04:55:28
【问题描述】:

我正在编写 rcpp 代码,我想在包“invgamma”中使用函数 dinvgamma(rinvgamma)。以下是我的所有代码。我尝试将包“invgamma”放入环境中,然后在其中调用函数作为 Rcpp::Function。

#include <Rcpp.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <R_ext/Utils.h>
using namespace Rcpp;
// [[Rcpp::export]]

RcppExport SEXP updatesigama2_mu(SEXP sigma2_mu, 
                                 SEXP mu, 
                                 SEXP u0, 
                                 SEXP v0, 
                                 SEXP K, 
                                 SEXP SS,
                                 SEXP acc,
                                 SEXP sigma2_mu_list)
{
  BEGIN_RCPP

  Rcpp::Environment invgamma("package:invgamma");
  Rcpp::Function dinvgamma = invgamma["dinvgamma"];
  Rcpp::Function rinvgamma = invgamma["rinvgamma"];


  double xacc = Rcpp::as<double>(acc);
  Rcpp::NumericVector xsigma2_mu_list(sigma2_mu_list);

  Rcpp::NumericVector xmu(mu);//vector mu
  double xsigma2_mu = Rcpp::as<double>(sigma2_mu);
  int xK = Rcpp::as<int>(K);
  int xSS = Rcpp::as<int>(SS);// time for irrecation 
  double xu0 = Rcpp::as<double>(u0);
  double xv0 = Rcpp::as<double>(v0);
  Rcpp::RNGScope scope;
  int c = 0; int d = 0;
  c = xu0 + 0.5*xK + 1;
  d = xv0 + 0.5*sum(xmu);
  for (int ss = 0; ss<xSS; ss++){//iteration
    Rcpp::NumericVector tmp = rinvgamma(1,0,1);//proposal distribution Normal(0,10)
    Rcpp::NumericVector u = Rcpp::runif(1);
    Rcpp::NumericVector a = dinvgamma(tmp[0], c, pow(d,-1),d, false ) * dinvgamma(xsigma2_mu,1,0,1,false)/
      (dinvgamma(xsigma2_mu,c,pow(d,-1),d,false)*dinvgamma(tmp[0],1,0,1,false))
    xsigma2_mu_list[1] = tmp[0];
    xsigma2_mu_list[2] = a[0];
    if ( u[0] <= a[0] ){
      xsigma2_mu = tmp[0];
      xacc += 1;
    }
  }

  return Rcpp::List::create(Rcpp::Named("sigma2_mu") = xsigma2_mu,
                            Rcpp::Named("acc") = xacc,
                            Rcpp::Named("sigma2_mu_list") = xsigma2_mu_list);

  END_RCPP
}

我将它用作以下形式,但它不起作用。它错过了排队的东西吗?

Rcpp::NumericVector a = dinvgamma(tmp[0], c, pow(d,-1),d, false ) * dinvgamma(xsigma2_mu,1,0,1,false)/
          (dinvgamma(xsigma2_mu,c,pow(d,-1),d,false)*dinvgamma(tmp[0],1,0,1,false))

【问题讨论】:

  • 请详细说明您的错误是什么,因为“如何将R包中的函数添加到rcpp代码中”已经回答了很多次了。
  • 错误是“没有匹配函数调用'dinvgamma'。”。看来我没有把这个功能变成环境。我的调用命令错了吗?
  • 我得到的唯一错误是invalid operands of types 'SEXP' and 'SEXP' to binary 'operator*'
  • 请尝试将edit 你的示例通过删除不需要产生错误的代码变成minimal reproducible example
  • 请注意,所有 invgamma 函数只是 gamma 函数的简单包装。后者可用作糖函数。

标签: r rcpp


【解决方案1】:

加载某个包中定义的 R 函数没有原则问题。但是,必须附加该软件包才能使用它的环境。请参阅示例中的函数rfunc()。在逆 Gamma 的情况下,更容易根据 Gamma 函数定义自己的函数。参见示例中的函数sugar()

示例:

#include <Rcpp.h>
// [[Rcpp::export]]
Rcpp::List rfunc() {
  Rcpp::Environment invgamma("package:invgamma");
  Rcpp::Function dinvgamma = invgamma["dinvgamma"];
  Rcpp::Function rinvgamma = invgamma["rinvgamma"];
  Rcpp::NumericVector tmp = rinvgamma(5, 1);
  Rcpp::NumericVector a = dinvgamma(tmp, 1);
  return Rcpp::List::create(Rcpp::Named("tmp") = tmp,
                Rcpp::Named("a") = a);
}


Rcpp::NumericVector rinvgamma(R_xlen_t n,
                  double shape,
                  double rate = 1.0) {
  return 1.0/Rcpp::rgamma(n, shape, rate);
}

Rcpp::NumericVector dinvgamma(Rcpp::NumericVector x,
                  double shape,
                  double rate = 1.0,
                  bool log = false) {
  Rcpp::NumericVector log_f = Rcpp::dgamma(1.0/x, shape, rate, true) - 2 * Rcpp::log(x);
  if (log) 
    return log_f;
  return Rcpp::exp(log_f);
}

// [[Rcpp::export]]
Rcpp::List sugar() {
  Rcpp::NumericVector tmp = rinvgamma(5, 1);
  Rcpp::NumericVector a = dinvgamma(tmp, 1);
  return Rcpp::List::create(Rcpp::Named("tmp") = tmp,
                Rcpp::Named("a") = a);
}


/*** R
library(invgamma)
set.seed(42)
rfunc()
set.seed(42)
sugar()
microbenchmark::microbenchmark(rfunc(), sugar())
*/

输出:

> library(invgamma)

> set.seed(42)

> rfunc()
$tmp
[1]  0.5156511  5.5426504  1.8711424 41.7271256  2.3376817

$a
[1] 0.5408323347 0.0271775313 0.1673728698 0.0005607317 0.1193024224


> set.seed(42)

> sugar()
$tmp
[1]  0.5156511  5.5426504  1.8711424 41.7271256  2.3376817

$a
[1] 0.5408323347 0.0271775313 0.1673728698 0.0005607317 0.1193024224


> microbenchmark::microbenchmark(rfunc(), sugar())
Unit: microseconds
    expr     min       lq      mean   median      uq      max neval
 rfunc() 115.098 117.1595 130.80325 117.9270 119.429 1342.420   100
 sugar()   7.333   8.3810  26.03649   9.2195  10.023 1657.404   100

使用 Rcpp 糖的性能提升令人印象深刻!

【讨论】:

  • 不错的一个。也许添加一个快速基准测试表明 Rcpp Sugar 优于调用 Rcpp::Function 接口?
  • @DirkEddelbuettel 好主意。性能提升确实令人印象深刻。
  • 作为一般规则,我们真的不想重复调用 R。
  • Ralf:我刚试着给你发电子邮件(关于“完全不同的东西”),但被退回了。你有替补吗?你能从那个备用邮箱发邮件吗?
  • 很好,和我一样的解决方案!我试图找到解决方案,但失败了。然后我使用 Gamma 分布和 Inverse Gamma 分布之间的关系,效果很好!无论如何,谢谢你的回答
猜你喜欢
  • 1970-01-01
  • 2021-01-26
  • 1970-01-01
  • 2020-11-13
  • 1970-01-01
  • 1970-01-01
  • 2021-02-25
  • 2018-04-28
  • 2020-10-01
相关资源
最近更新 更多