Chapter 24 NA NaN Inf NULL
24.1 Notations of NA NaN Inf
To express the value of Inf -Inf NaN in Rcpp, use the symbol R_PosInf R_NegInf R_NaN.
| R | Rcpp |
|---|---|
Inf |
R_PosInf |
-Inf |
R_NegInf |
NaN |
R_NaN |
On the other hand, for NA, different symbol of NA are defined for each Vector type.
| Vector | symbol of NA |
|---|---|
NumericVector |
NA_REAL |
IntegerVector |
NA_INTEGER |
LogicalVector |
NA_LOGICAL |
CharacterVector |
NA_STRING |
The following code example shows how to use these symbols to create Vector object.
24.2 Evaluating NA NaN Inf
24.2.1 Evaluating all the elements of a vector at once
To evaluate all the NA NaN Inf -Inf elements in a vector at once, use the function is_na() is_nan() is_infinite().
In the code example below, we create a vector containing NA NaN Inf -Inf and evaluate it. From this example we can see that the is_na() evaluates both NA andNaN as TRUE (same as R’s is.na()).
NumericVector v =
NumericVector::create( 1, NA_REAL, R_NaN, R_PosInf, R_NegInf);
LogicalVector l1 = is_na(v);
LogicalVector l2 = is_nan(v);
LogicalVector l3 = is_infinite(v);
Rcout << l1 << "\n"; // 0 1 1 0 0
Rcout << l2 << "\n"; // 0 0 1 0 0
Rcout << l3 << "\n"; // 0 0 0 1 1You can remove NA NaN Inf from a vector by using these functions. You can also use na_omit() to remove NA.
The code example below shows how to remove NA from a vector using the is_na() and na_omit().
// Creating a Vector object containg NA
NumericVector v =
NumericVector::create( 1, NA_REAL, 2, NA_REAL, 3);
// Removeing NA from the vector
NumericVector v1 = v[!is_na(v)];
NumericVector v2 = na_omit(v);
24.2.2 Evaluating single element of a vector
If you want to evaluate NA NaN Inf -Inf on single element of a vector, use the static member function Vector::is_na(), traits::is_nan<RTYPE>(), traits:: is_infinite<RTYPE>(). In RTYPE, specify SEXPTYPE of the vector to be evaluated.
// [[Rcpp::export]]
void rcpp_is_na2() {
// Creating Vector object containing NA NaN Inf -Inf
NumericVector v =
NumericVector::create(1, NA_REAL, R_NaN, R_PosInf, R_NegInf);
// Evaluating the value for each element of the vector
int n = v.length();
for (int i = 0; i < n; ++i) {
if(NumericVector::is_na(v[i]))
Rprintf("v[%i] is NA.\n", i);
if(Rcpp::traits::is_nan<REALSXP>(v[i]))
Rprintf("v[%i] is NaN.\n", i);
if(Rcpp::traits::is_infinite<REALSXP>(v[i]))
Rprintf("v[%i] is Inf or -Inf.\n", i);
}
}Here is the list of SEXPTYPE of the major Vector class.
| SEXPTYPE | Vector |
|---|---|
LGLSXP |
LogicalVector |
INTSXP |
IntegerVector |
REALSXP |
NumericVector |
CPLXSXP |
ComplexVector |
STRSXP |
CharacterVector (StringVector) |
24.3 NULL
You use R_NilValue to handleNULL in Rcpp. The code example below shows how to check NULL in the elements of a List object and how to assign NULL to clear the value of an attribute.
// [[Rcpp::export]]
List rcpp_list()
{
// Create a List object with element names
// One of the two elements is NULL
List L = List::create(Named("x",NumericVector({1,2,3})),
Named("y",R_NilValue));
// Checking NULL
for(int i=0; i<L.length(); ++i){
if(L[i]==R_NilValue) {
Rprintf("L[%i] is NULL.\n\n", i+1);
}
}
// Delete the value of the attribute (element name) of the object
L.attr("names") = R_NilValue;
return(L);
}Execution result
> rcpp_list()
L[2] is NULL.
[[1]]
[1] 1 2 3
[[2]]
NULL
24.4 Points to note when handling NA with Rcpp
Internally NA_INTEGER and NA_LOGICAL are equivalent to the minimum value of int (-2147483648). Although, functions and operators defined in Rcpp handle the minimum value of int appropriately asNA (that is, make the result of operation on NA element as NA). Standard C++ functions and operators treat the minimum value of int as integer value. So if you add 1 to NA_INTEGER, the element is no longer minimum value of int, so it is not treated as NA.
In addition, if you assign NA_LOGICAL to bool type, it will always be evaluated as true. This is because bool evaluates all numbers other than 0 as true.
On the other hand, since nan and inf are defined in double, the result of the operation on nan inf in standard C ++ will be the same result as R.
The table below summarizes how values are evaluated when assigning the value of NA Inf -Inf NaN to Vector or scalar type in C++.
| NA | NaN | Inf | -Inf | |
|---|---|---|---|---|
NumericVector |
NA_REAL |
R_NaN |
R_PosInf |
R_NegInf |
IntegerVector |
NA_INTEGER |
NA_INTEGER |
NA_INTEGER |
NA_INTEGER |
LogicalVector |
NA_LOGICAL |
NA_LOGICAL |
NA_LOGICAL |
NA_LOGICAL |
CharacterVector |
NA_STRING |
“NaN” | “Inf” | “-Inf” |
String |
NA_STRING |
“NaN” | “Inf” | “-Inf” |
double |
nan |
nan |
inf |
-inf |
int |
-2147483648 | -2147483648 | -2147483648 | -2147483648 |
bool |
true |
true |
true |
true |
The code example below shows the difference in results when computing using the Rcpp operator and the standard C++ operator against NA_INTEGER. From this result, the operator of Rcpp evaluates the result of the operation on NA as NA, but you can see that the standard C++ operator treats NA_INTEGER as just a integer value.
// [[Rcpp::export]]
List rcpp_na_sum(){
// Creating an integer vector containing NA
IntegerVector v1 = IntegerVector::create(1,NA_INTEGER,3);
// Applying the "+" operator between vector and scalar defined in Rcpp
IntegerVector res1 = v1 + 1;
// Applying the "+" operator between int and int defined in standard C++
IntegerVector res2(3);
for(int i=0; i<v1.length(); ++i){
res2[i] = v1[i] + 1;
}
// Outputing the result as named list
return List::create(Named("Rcpp plus", res1),
Named("C++ plus", res2));
}Execution result
> rcpp_na_sum()
$`Rcpp plus`
[1] 2 NA 4
$`C++ plus`
[1] 2 -2147483647 4