我正在将基于R的代码转换为基于Rcpp的代码.我的职责是:
NumericMatrix createMatrixOfLinkRatiosC(NumericMatrix matr, double threshold4Clean) {
int i,j; 
NumericMatrix myMatr(matr.nrow(),matr.ncol());
myMatr=matr;
....;
}
我想处理对threshold4Clean缺失的函数的调用,但我没有找到怎么办...任何帮助将不胜感激.
Kev*_*hey 26
R有两个NaN和NA(实际上是一种特殊的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  |
+---------------------+
不幸的是,这是一个令人困惑的景观,但这应该给你一些权力.
既RCPP和RcppArmadillo具有谓词来测试NA,NaN(的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)
***/
我们初始化一个零矩阵,并测试参数.如果它是有限的(即不是NA或Inf或NaN),那么我们添加该值.如果您愿意,您也可以单独测试各种可能性.
这会产生所需的结果:没有第二个参数的默认值NAapply,我们得到一个零的矩阵.
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> 
我一直在测试这个,可以揭示一些可能性。
对于单个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有一些注意事项:
NA(都存储为int)等于int(-2147483648)的最小值。double,你可以直接使用什么Rcpp用,即R_isnancpp。等效地,可以使用ISNAN宏。double上面的方法检查实部和虚部。字符NA很棘手,因为它是一个单身人士,所以地址很重要。我个人一直在测试在不存储的情况下std::string对R 字符进行操作以避免复制的方法,即char*直接使用。我发现有效的是在.cpp文件中声明它:
static const char *na_string_ptr = CHAR(Rf_asChar(NA_STRING));
并且,根据这个答案,对 a Rcpp::StringVectoror做这样的事情Rcpp::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 做类似的事情,但我还没有尝试过。