- Rcppのsugarというのは、Rcppパッケージで提供される、cppコードとして使う関数なんだけれども、その名称がうまいことR本体の関数と同じように作ってあって、Rの関数を思い出しながらcppを書けるようにしてくれている一群の「Rユーザを甘やかす関数」のこと
- その一覧は以下のような感じ
+ *, -, /, pow, <, <=, >, >=, ==, !=, !.
Math functions: abs(), acos(), asin(), atan(), beta(), ceil(), ceiling(), choose(), cos(), cosh(), digamma(), exp(), expm1(), factorial(), floor(), gamma(), lbeta(), lchoose(), lfactorial(), lgamma(), log(), log10(), log1p(), pentagamma(), psigamma(), round(), signif(), sin(), sinh(), sqrt(), tan(), tanh(), tetragamma(), trigamma(), trunc().
Scalar summaries: mean(), min(), max(), sum(), sd(), and (for vectors) var().
Vector summaries: cumsum(), diff(), pmin(), and pmax().
Finding values: match(), self_match(), which_max(), which_min().
Dealing with duplicates: duplicated(), unique().
d/q/p/r for all standard distributions.
- このリストの末尾にあるように、確率分布関数のd/p/q/rが一通りsugar化提供されている
- でも、ちょっと使うにはコツがいるようなので、メモ
- まず、Rで言うところのpbeta()が使いたいとする
- 調べものはこちらのRcpp本家(らしい)サイトにて、"pbeta"で検索
- そうするとこちらに飛ぶ。さらに、"Definition at line 61 of file Rmath.h."との記載があり、Rmath.hの61行目を見ればよいことがわかる。Rmath.hにリンクがあるので飛んでいけば、確かにコードが見られて、その61行目が確認できる
- beta分布関係の行は次の通り
60 inline double dbeta(double x, double a, double b, int lg) { return ::Rf_dbeta(x, a, b, lg); }
61 inline double pbeta(double x, double p, double q, int lt, int lg) { return ::Rf_pbeta(x, p, q, lt, lg); }
62 inline double qbeta(double a, double p, double q, int lt, int lg) { return ::Rf_qbeta(a, p, q, lt, lg); }
63 inline double rbeta(double a, double b) { return ::Rf_rbeta(a, b); }
64
- pbetaに関して言えば、double x, double p, double q, int lt, int lgの5引数であることがわかる
- また、cppでのpbeta関数というのは、さらに別途定義された::Rf_pbetaのことであることがわかる。このRf_は"Rの関数で言うところの"という書き方ルール(Rcppのパッケージを作った人のルール)で、"::"もcppとRとをつなぐための記法。cxxfunction()を使うとき(inline)では、その記法やらルールやらをいちいち書かなくてもよいように"sugar"化しているからcppでpbetaと打てばよくなっている
- ただし、引数の具合は違う
- Rのpbeta()は、そのヘルプに以下のように書かれているように、必須引数が3つ、オプション引数が3つであって、「5個」ではない
pbeta(q, shape1, shape2, ncp = 0, lower.tail = TRUE, log.p = FALSE)
- cppの4つの関数d,p,q,rと、その引数の組み合わせを見てみる
- d : x,a,b,lg
- p : x,p,q,lt,lg
- q : a,p,q,lt,lg
- r : a,b
- rには2引数しかない。Rのrbetaには、発生させる乱数の個数の引数と、ベータ分布を決める2引数を与えるが、cppのrには2つしかない。2つはベータ分布を決めるのに必須だから、cppのrbeta関数は、乱数を1個返す関数で、a,bはベータ分布の形を決める引数であることがわかる
- 確認してみる。cppのrbeta関数は発生乱数の個数もとるんだな、これが…
#include <RcppArmadillo.h>
using namespace arma;
using namespace Rcpp;
double testRbeta(double a, double b){
double ret = Rf_rbeta(a,b);
return ret;
}
vec testRbeta2(int n, double a, double b){
vec ret = rbeta(n,a,b);
return ret;
}
double testRbeta3(double a, double b){
double ret = ::Rf_rbeta(a,b);
return ret;
}
Rcpp::sourceCpp("testbeta.cpp")
testRbeta(3,5)
testRbeta2(100,3,5)
testRbeta3(3,5)
#include <RcppArmadillo.h>
using namespace arma;
using namespace Rcpp;
double testPbeta(double x,double p, double q,int lt=0,int lg=0){
double ret = Rf_pbeta(x,p,q,lt,lg);
return ret;
}
- 以下の様子からltはlower.tailのT/Fに、lgはlog.pのT/Fに対応していることがわかる
> testPbeta(0.6,3,5,1)
[1] 0.903744
> testPbeta(0.6,3,5)
[1] 0.096256
> testPbeta(0.6,3,5,0)
[1] 0.096256
> pbeta(0.6,3,5,lower.tail=FALSE)
[1] 0.096256
> testPbeta(0.6,3,5,1)
[1] 0.903744
> pbeta(0.6,3,5,lower.tail=TRUE)
[1] 0.903744
> pbeta(0.6,3,5)
[1] 0.903744
> pbeta(0.6,3,5,log.p=TRUE)
[1] -0.1012091
> testPbeta(0.6,3,5,1,1)
[1] -0.1012091
#include <RcppArmadillo.h>
using namespace arma;
using namespace Rcpp;
double testQchisq(double p, double df, int lt, int lg){
double ret = Rf_qchisq(p,df,lt,lg);
return ret;
}
> testQchisq(0.99,1,0,0)
[1] 0.0001570879
> testQchisq(0.01,1,0,0)
[1] 6.634897
> qchisq(0.01,1,lower.tail=FALSE)
[1] 6.634897
> qchisq(0.01,1,lower.tail=TRUE)
[1] 0.0001570879
> testQchisq(0.01,1,1,0)
[1] 0.0001570879
-
- cppのRf_qcihsq()の最後のint lgは0以外の値はとれないようだ…