我正在将基于R的代码转换为基于Rcpp的代码.我的职责是:
NumericMatrix createMatrixOfLinkRatiosC(NumericMatrix matr, double threshold4Clean) {
int i,j;
NumericMatrix myMatr(matr.nrow(),matr.ncol());
myMatr=matr;
....;
}
Run Code Online (Sandbox Code Playgroud)
我想处理对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 |
+---------------------+
Run Code Online (Sandbox Code Playgroud)
和Rcpp:
+-------------------------+
| Function | NaN | NA |
+-------------------------+
| Rcpp::is_na | t | t |
| Rcpp::is_nan | t | f |
+-------------------------+
Run Code Online (Sandbox Code Playgroud)
并从R解释器(注意:Rcpp尝试匹配此,而不是R/C API):
+---------------------+
| Function | NaN | NA |
+---------------------+
| is.na | t | t |
| is.nan | t | f |
+---------------------+
Run Code Online (Sandbox Code Playgroud)
不幸的是,这是一个令人困惑的景观,但这应该给你一些权力.
既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)
***/
Run Code Online (Sandbox Code Playgroud)
我们初始化一个零矩阵,并测试参数.如果它是有限的(即不是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>
Run Code Online (Sandbox Code Playgroud)
我一直在测试这个,可以揭示一些可能性。
对于单个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]);
}
}
Run Code Online (Sandbox Code Playgroud)
如果您想在不使用的情况下进行检查,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));
Run Code Online (Sandbox Code Playgroud)
并且,根据这个答案,对 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;
Run Code Online (Sandbox Code Playgroud)
最后一个仍然使用Rcpp,但我可以使用它一次进行初始设置,然后只使用char指针。我确信有一种方法可以用 R 的 API 做类似的事情,但我还没有尝试过。