【问题标题】:Rcpp function check if missing valueRcpp 函数检查是否缺少值
【发布时间】:2014-10-07 16:45:37
【问题描述】:

我正在将基于 R 的代码转换为基于 Rcpp 的代码。我的函数的负责人是:

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

}

我想处理对缺少 threshold4Clean 的函数的调用,但我不知道该怎么做...任何帮助将不胜感激。

【问题讨论】:

  • 当你说缺失时,你的意思是“NA”还是你的意思是你没有向它传递任何价值?

标签: r rcpp


【解决方案1】:

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

来自 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  |
+---------------------+

不幸的是,这是一个令人困惑的场景,但这应该会让你有点力量。

【讨论】:

  • 做得很好。也许我们也应该把它放到 Rcpp FAQ 中?
【解决方案2】:

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> 

【讨论】:

  • 谢谢 Dirk,你也有纯 Rcpp 的例子吗?
【解决方案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 做类似的事情, 但这是我还没有尝试过的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-17
    • 1970-01-01
    相关资源
    最近更新 更多