Rcpp函数检查是否缺少值

时间:2014-10-07 16:45:38

标签: r rcpp

我将基于R的代码转换为基于Rcpp的代码。我的职责是:

NumericMatrix createMatrixOfLinkRatiosC(NumericMatrix matr, double threshold4Clean) {
int i,j; 
NumericMatrix myMatr(matr.nrow(),matr.ncol());
myMatr=matr;
....;

}

我想处理对缺少threshold4Clean的函数的调用,但我没有找到该怎么办...将非常感谢任何帮助。

3 个答案:

答案 0 :(得分:24)

R同时包含NaNNA(实际上是一种特殊的NaN)来表示缺失值。这一点很重要,因为有许多函数可以检查值是NaN - y(NA还是NaN):

来自R / C API的函数的一些真值表(注意令人沮丧的缺乏一致性)

+---------------------+
| Function | NaN | NA |
+---------------------+
| ISNAN    |  t  | t  |
| R_IsNaN  |  t  | f  |
| ISNA     |  f  | t  |
| R_IsNA   |  f  | t  |
+---------------------+

和Rcpp:

+-------------------------+
| Function     | NaN | NA |
+-------------------------+
| Rcpp::is_na  |  t  | t  |
| Rcpp::is_nan |  t  | f  |
+-------------------------+

并从R解释器(注意:Rcpp尝试匹配此,而不是R / C API):

+---------------------+
| Function | NaN | NA |
+---------------------+
| is.na    |  t  | t  |
| is.nan   |  t  | f  |
+---------------------+

不幸的是,这是一个令人困惑的环境,但这应该会让你有所帮助。

答案 1 :(得分:7)

Rcpp和RcppArmadillo都有谓词来测试NANaN(R扩展名)和Inf

这是一个简短的RcppArmadillo示例:

#include <RcppArmadillo.h>

// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
arma::mat foo(int n, double threshold=NA_REAL) {
  arma::mat M = arma::zeros<arma::mat>(n,n);
  if (arma::is_finite(threshold)) M = M + threshold;
  return M;
}

/*** R
foo(2)
foo(2, 3.1415)
***/

我们初始化一个零矩阵,并测试参数。如果它是有限的(即不是NAInfNaN),那么我们添加该值。如果你愿意,你也可以单独测试各种可能性。

这会产生所需的结果:没有第二个参数,默认值NA适用,我们得到一个零矩阵。

R> Rcpp::sourceCpp("/tmp/giorgio.cpp")

R> foo(2)
     [,1] [,2]
[1,]    0    0
[2,]    0    0

R> foo(2, 3.1415)
       [,1]   [,2]
[1,] 3.1415 3.1415
[2,] 3.1415 3.1415
R> 

答案 2 :(得分:3)

我已经对此进行了测试,可以揭示一些可能性。

对于单个SEXP target,我使用的Rcpp选项是:

switch(TYPEOF(target)) {
case INTSXP:
    return Rcpp::traits::is_na<INTSXP>(Rcpp::as<int>(target));
case REALSXP:
    return Rcpp::traits::is_na<REALSXP>(Rcpp::as<double>(target));
case LGLSXP:
    return Rcpp::traits::is_na<LGLSXP>(Rcpp::as<int>(target));
case CPLXSXP:
    return Rcpp::traits::is_na<CPLXSXP>(Rcpp::as<Rcomplex>(target));
case STRSXP: {
    Rcpp::StringVector vec(target);
    return Rcpp::traits::is_na<STRSXP>(vec[0]);
}
}

如果您不想使用Rcpp进行检查,请注意以下几点:

  • here所述, 整数和逻辑NA(均存储为int)等于int的最小值(-2147483648)。
  • 对于double,您可以直接使用Rcpp uses, 即R_isnancpp。 等效地,可以使用ISNAN macro
  • 对于复数,您可以使用上方的double方法检查实部和虚部。

字符NA很棘手,因为它是一个单例,所以地址很重要。 我个人一直在测试使用R字符进行操作而不存储std::string以避免复制的方法, 即直接使用char*。 我发现有效的方法是在.cpp文件中声明此内容:

static const char *na_string_ptr = CHAR(Rf_asChar(NA_STRING));

,并且基于this answer, 为Rcpp::StringVectorRcpp::StringMatrix x做这样的事情:

Rcpp::CharacterVector one_string = Rcpp::as<Rcpp::CharacterVector>(x[i]);
char *ptr = (char *)(one_string[0]);
return ptr == na_string_ptr;

最后一个仍然使用Rcpp, 但我可以将其用于一次初始设置,然后仅使用char指针。 我敢肯定,有一种方法可以对R的API进行类似的处理, 但这是我尚未尝试过的东西。