使用RcppArmadillo的dnorm函数

5

我正在使用R,尝试在此文件上运行sourceCpp

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

using namespace arma; 
using namespace Rcpp;

// [[Rcpp::export]]
vec dnormLog(vec x, vec means, vec sds) {
    int n = x.size();
    vec res(n);
    for(int i = 0; i < n; i++) {
        res[i] = log(dnorm(x[i], means[i], sds[i]));
    }
return res;
}

请参考这个答案,了解我从哪里得到这个函数。以下是报错信息: no matching function for call to 'dnorm4' 正是我希望通过使用循环来避免的确切错误,因为引用的答案提到dnorm只对其第一个参数向量化。我担心答案很明显,但我已经尝试在dnorm之前添加R::,尝试使用NumericVector代替vec,而不使用log()。但都没有成功。然而,在dnorm之前添加R::确实会产生另一个错误:
too few arguments to function call, expected 4, have 3; did you mean '::dnorm4'?

如果只是将上面的dnorm替换为R::dnorm4,并不能解决问题。

1个回答

9

这里有两个很好的教学时刻:

  1. 注意命名空间。如果不确定,请不要使用全局。
  2. 检查头文件以获取实际的定义。在标量版本R::dnorm()中,您错过了第四个参数。

这是一个修复后的版本,还包括了您可能会感兴趣的第二个变体:

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

// [[Rcpp::export]]
arma::vec dnormLog(arma::vec x, arma::vec means, arma::vec sds) {
  int n = x.size();
  arma::vec res(n);
  for(int i = 0; i < n; i++) {
    res[i] = std::log(R::dnorm(x[i], means[i], sds[i], FALSE));
  }
  return res;
}

// [[Rcpp::export]]
arma::vec dnormLog2(arma::vec x, arma::vec means, arma::vec sds) {
  int n = x.size();
  arma::vec res(n);
  for(int i = 0; i < n; i++) {
    res[i] = R::dnorm(x[i], means[i], sds[i], TRUE);
  }
  return res;
}


/*** R
dnormLog( c(0.1,0.2,0.3), rep(0.0, 3), rep(1.0, 3))
dnormLog2(c(0.1,0.2,0.3), rep(0.0, 3), rep(1.0, 3))
*/

当我们进行数据查询时,这两个查询将返回相同的结果,因为R API允许我们请求进行对数运算。
R> sourceCpp("/tmp/dnorm.cpp")

R> dnormLog( c(0.1,0.2,0.3), rep(0.0, 3), rep(1.0, 3))
          [,1]
[1,] -0.923939
[2,] -0.938939
[3,] -0.963939

R> dnormLog2(c(0.1,0.2,0.3), rep(0.0, 3), rep(1.0, 3))
          [,1]
[1,] -0.923939
[2,] -0.938939
[3,] -0.963939
R> 

1
关于命名空间的评论非常准确。在我的经验中,using namespace [...]引起的问题比解决的问题要多得多。 - nrussell
啊,我现在明白了。对于第四个参数问题,我最初尝试传递 log = TRUE,但我应该传递 TRUE。我现在记得在文档中看到传递命名参数所涉及的复杂性。感谢您提供非常有用的答案。 - Jason

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