如何正确使用Rcpp::pt()函数

11

我正在阅读《Seamless R and C++ Integration with Rcpp》的第四章,遇到了一个小问题。

在 "列表 4.13" 中,这本书给出了一个关于如何使用 R 函数的例子。我尝试使用其他函数(不同于示例),并且取得了成功。我的代码在这里:

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::DataFrame myrandom(Rcpp::NumericVector x) {
  int n = x.size();
  Rcpp::NumericVector y1(n), y2(n), y3(n);

  y1 = Rcpp::pexp(x,1.0,1,0);
  y2 = Rcpp::pnorm(x,0.0,1.0,1,0);
  y3 = Rcpp::ppois(x,3.0,1,0);

  return Rcpp::DataFrame::create(Rcpp::Named("Exp") = y1,Rcpp::Named("Norm") = y2, Rcpp::Named("Pois") = y3);
}


sourceCpp("random.cpp")
myrandom(c(0.5,1))

在这种情况下是可以的,但是当我尝试使用Rcpp::pt时,我没有成功。我的代码在这里。

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::DataFrame myrandom2(Rcpp::NumericVector x) {
  int n = x.size();
  Rcpp::NumericVector y1(n);

  y1 = Rcpp::pt(x,3.0,0,1,0);

  return Rcpp::DataFrame::create(Rcpp::Named("T") = y1);
}

sourceCpp("random2.cpp")
myrandom2(c(0.5,1))

/Library/Frameworks/R.framework/Versions/3.0/Resources/library/Rcpp/include/Rcpp/stats/nt.h: In function ‘Rcpp::stats::P2<RTYPE, NA, T> Rcpp::pt(const Rcpp::VectorBase<RTYPE, NA, VECTOR>&, double, double, bool, bool) [with int RTYPE = 14, bool NA = true, T = Rcpp::Vector<14>]’:
random2.cpp:8:   instantiated from here
/Library/Frameworks/R.framework/Versions/3.0/Resources/library/Rcpp/include/Rcpp/stats/nt.h:25: error: invalid conversion from ‘double (*)(double, double, int, int)’ to ‘double (*)(double, double, double, int, int)’
/Library/Frameworks/R.framework/Versions/3.0/Resources/library/Rcpp/include/Rcpp/stats/nt.h:25: error:   initializing argument 1 of ‘Rcpp::stats::P2<RTYPE, NA, T>::P2(double (*)(double, double, double, int, int), const Rcpp::VectorBase<RTYPE, NA, VECTOR>&, double, double, bool, bool) [with int RTYPE = 14, bool NA = true, T = Rcpp::Vector<14>]’
make: *** [random2.o] Error 1
llvm-g++-4.2 -arch x86_64 -I/Library/Frameworks/R.framework/Resources/include -DNDEBUG  -I/usr/local/include  -I"/Library/Frameworks/R.framework/Versions/3.0/Resources/library/Rcpp/include"    -fPIC  -mtune=core2 -g -O2  -c random2.cpp -o random2.o 

当我使用Rcpp::pt(x,3)时,我希望能够控制函数的参数。
pt(q, df, ncp, lower.tail = TRUE, log.p = FALSE)

我觉得我没有正确使用这个函数,但我不知道哪里出了问题。


1
由于您下面有一些似乎回答了您的问题,请考虑通过点击其投票计数下方的勾选标记之一将其中一个标记为“已接受”。这显示哪个答案对您最有帮助,并将声誉点分配给答案的作者(以及您!)。这是该网站通过赞成和接受答案来识别好问题和答案的想法的一部分。 - jub0bs
2个回答

8

C++编译器的错误信息不是很好吗? ;-)

我认为你刚刚帮助解决了一个很老的bug。对于t和F,R实际上有两个函数组(r|p|q|d)t和(r|p|q|d)nt(对f和nf也是如此),其中第二种形式允许使用非中心性参数。而我认为nt.h的标头是错误的。

如果您在include/Rcpp/stats/nt.h文件中进行此更改

@@ -22,7 +22,7 @@
 #ifndef Rcpp__stats__nt_h
 #define Rcpp__stats__nt_h

-RCPP_DPQ_2(t,::Rf_dt,::Rf_pt,::Rf_qt)
+RCPP_DPQ_2(nt,::Rf_dnt,::Rf_pnt,::Rf_qnt)

 #endif

(您只需在标题中进行编辑,无需重新安装)然后事情似乎就可以工作:
#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::DataFrame myrandom(Rcpp::NumericVector x) {
  Rcpp::NumericVector y1, y2, y3, y4, y5, y6, y7, y8;

  y1 = Rcpp::pexp(x,1.0,1,0);
  y2 = Rcpp::pnorm(x,0.0,1.0,1,0);
  y3 = Rcpp::ppois(x,3.0,1,0);
  y4 = Rcpp::pt(x,3.0,1,0);
  y5 = Rcpp::pnt(x,3.0,2,TRUE,FALSE);
  y6 = Rcpp::pnt(x,3.0,2,TRUE,TRUE);
  y7 = Rcpp::pnt(x,3.0,2,FALSE,TRUE);
  y8 = Rcpp::pnt(x,3.0,2,FALSE,FALSE);

  return Rcpp::DataFrame::create(Rcpp::Named("Exp") = y1,
                                 Rcpp::Named("Norm") = y2, 
                                 Rcpp::Named("Pois") = y3,
                                 Rcpp::Named("t") = y4,
                                 Rcpp::Named("nt1") = y5,
                                 Rcpp::Named("nt2") = y6,
                                 Rcpp::Named("nt3") = y7,
                                 Rcpp::Named("nt4") = y8);
}

我仍然需要将数字与R进行比较,但至少现在它可以构建。(TRUE/FALSE与1/0无关紧要;这会被正确转换)。

编辑:这里是一些输出:
> sourceCpp("/tmp/so1.cpp")  
R> myrandom(seq(0.2, 0.5, by=0.1))  
       Exp     Norm      Pois        t       nt1      nt2        nt3      nt4   
1 0.181269 0.579260 0.0497871 0.572865 0.0351335 -3.34860 -0.0357655 0.964866   
2 0.259182 0.617911 0.0497871 0.608118 0.0434710 -3.13566 -0.0444441 0.956529  
3 0.329680 0.655422 0.0497871 0.642032 0.0535219 -2.92767 -0.0550074 0.946478  
4 0.393469 0.691462 0.0497871 0.674276 0.0654790 -2.72603 -0.0677212 0.934521   
R>   

这就是不经过测试的代价。如果有任何人想以系统化的方式解决https://github.com/RcppCore/Rcpp/issues/29,他们将受到热烈欢迎。 - Romain Francois
实际上,这个测试已经存在了好几年,但是是错误的。我们两个都在那个问题上犯了错。话虽如此,额外的测试确实会受到欢迎。 - Dirk Eddelbuettel

5

似乎学生t分布没有非中心参数ncp; 来自 Rmath.h:

/* Student t Distibution */
inline double dt(double x, double n, int lg) { return ::Rf_dt(x, n, lg); }
inline double pt(double x, double n, int lt, int lg) { return ::Rf_pt(x, n, lt, lg); }
inline double qt(double p, double n, int lt, int lg) { return ::Rf_qt(p, n, lt, lg); }
inline double rt(double n) { return ::Rf_rt(n); }

我可以在以下更改的情况下编译和执行你的代码:

#include <Rcpp.h>

// [[Rcpp::export]]
Rcpp::DataFrame myrandom2(Rcpp::NumericVector x) {
  int n = x.size();
  Rcpp::NumericVector y1(n);

  y1 = Rcpp::pt(x, 3.0, false, true);

  return Rcpp::DataFrame::create(Rcpp::Named("T") = y1);
}

1
不错的回答,@rcs,但是它绕过了如何使用添加的“ncp”参数来完成此操作的实际问题。我们在那里有一个错误,我之前提交了一个修复程序,并将在今晚提交一些更多的单元测试。 - Dirk Eddelbuettel

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