使用Rcpp Sugar将均值和标准差传递给dnorm()函数

3

我正在将一些R代码转换为Rcpp代码,需要计算给定一组均值向量和标准差向量的情况下,一组观测值的似然。如果假设均值为0,标准差为1,则可以编写以下函数(运行此函数需要加载“inline”和“Rcpp”软件包):

dtest1 = cxxfunction(signature( x = "numeric"),
                      'Rcpp::NumericVector xx(x);
                       return::wrap(dnorm(xx, 0.0, 1.0));', 
                       plugin='Rcpp')

并且结果如预期。
> dtest1(1:3) 
[1] 0.241970725 0.053990967 0.004431848

然而,如果我尝试创建一个函数
dtest2 = cxxfunction(signature( x = "numeric", y="numeric", z="numeric" ),
                  'Rcpp::NumericVector xx(x);
                   Rcpp::NumericVector yy(y);
                   Rcpp::NumericVector zz(z);
                   return::wrap(dnorm(xx, yy, zz));',
                   plugin='Rcpp')

我希望能够传入不同的均值和标准差,但是会出现下面显示的错误。有没有办法让我尝试创建的函数生效,或者我需要手动编写正态密度函数?

错误信息

Error in compileCode(f, code, language = language, verbose = verbose) :   
    Compilation ERROR, function(s)/method(s) not created! file31c82bff9d7c.cpp: In function ‘SEXPREC* file31c82bff9d7c(SEXP, SEXP, SEXP)’:
file31c82bff9d7c.cpp:33:53: error: no matching function for call to 
     ‘dnorm4(Rcpp::NumericVector&, Rcpp::NumericVector&, Rcpp::NumericVector&)’
file31c82bff9d7c.cpp:33:53: note: candidates are:
/home/chris/R/x86_64-pc-linux-gnu-library/3.0/Rcpp/include/Rcpp/stats/norm.h:106:1: 
     note: template<int RTYPE, bool NA, class T> Rcpp::stats::D0<RTYPE, NA, T> Rcpp::dnorm4(const Rcpp::VectorBase<RTYPE, NA, VECTOR>&, bool)
/home/chris/R/x86_64-pc-linux-gnu-library/3.0/Rcpp/include/Rcpp/stats/norm.h:107:1: 
     note: template<int RTYPE, bool NA, class T> Rcpp::stats::D1<RTYPE, NA, T> Rcpp::dnorm4(const Rcpp::VectorBase<RTYPE, NA, VECTOR>&, double, bool)
/home/chris/R/x86_64-pc-linux-gnu-library/3.0/Rcpp/include/Rcpp/stats/norm.h:108:1: 
     note: template<int RTYPE, bool NA, class T> Rcpp::stats::D2<RTYPE, NA, T> Rcpp::dnorm4(const Rcpp::VectorBase<RTYPE, NA,
In addition: Warning message:
running command '/usr/lib/R/bin/R CMD SHLIB file31c82bff9d7c.cpp 2> file31c82bff9d7c.cpp.err.txt' had status 1

错误信息显示您使用了 dnorm4 函数。(然而,在 Mac 上我也遇到了类似的错误。) - IRTFM
@Dwin 我不明白为什么错误提示说我使用了dnorm4函数,因为我是从我的电脑上复制的代码,而这就是错误信息。此外,我也很难理解Rcpp sugar的工作原理,所以这也是问题的一部分吧。 - caburke
我也不理解,但是我可以用这段代码产生相同的错误:dtest = cxxfunction(signature( x = "numeric" ), 'Rcpp::NumericVector xx(x); return::wrap(dnorm(xx, 0, 1));', plugin='Rcpp') 唯一的区别是均值和标准差参数不是十进制形式。 - IRTFM
1个回答

7

糖果dnorm仅针对第一个参数进行向量化。

为了简化(虽然稍微有点复杂,但我们现在不需要关注这个),调用:

dnorm(xx, 0.0, 1.0)

使用重载
NumericVector dnorm( NumericVector, double, double )

第二个调用尝试使用类似于的东西。
NumericVector dnorm( NumericVector, NumericVector, NumericVector )

这个功能尚未实现。我们可以实现它,但需要将其提高到我们的优先级列表中。

在此期间,很容易编写一个小包装器,如下所示(这不处理参数长度等):

NumericVector my_dnorm( NumericVector x, NumericVector means, NumericVector sds){
    int n = x.size() ;
    NumericVector res(n) ;
    for( int i=0; i<n; i++) res[i] = R::dnorm( x[i], means[i], sds[i] ) ;
    return res ;
}

那么为什么使用 dnorm(xx, 1,0) 调用会抛出相同的错误? - IRTFM
我猜编译器会寻找一个使用int作为第二个和第三个参数的重载函数,而对于 R api 中的函数则感到困惑。 - Romain Francois
也许你需要将一个布尔值传递给 dnorm 函数,并将 log 设置为 false,因为 R 中的 dnorm 函数具有此额外选项。 - chandler

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