Skip to content

Commit 9e23c89

Browse files
added nan parameter to fcoalesce
1 parent bfa049c commit 9e23c89

File tree

4 files changed

+15
-9
lines changed

4 files changed

+15
-9
lines changed

R/wrappers.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
# Very small (e.g. one line) R functions that just call C.
33
# One file wrappers.R to avoid creating lots of small .R files.
44

5-
fcoalesce = function(...) .Call(Ccoalesce, list(...), FALSE)
6-
setcoalesce = function(...) .Call(Ccoalesce, list(...), TRUE)
5+
fcoalesce = function(..., nan=NA) .Call(Ccoalesce, list(...), FALSE, nan_is_na(nan))
6+
setcoalesce = function(..., nan=NA) .Call(Ccoalesce, list(...), TRUE, nan_is_na(nan))
77

88
fifelse = function(test, yes, no, na=NA) .Call(CfifelseR, test, yes, no, na)
99
fcase = function(..., default=NA) {

man/coalesce.Rd

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ Fill in missing values in a vector by successively pulling from candidate vector
77
Written in C, and multithreaded for numeric and factor types.
88
}
99
\usage{
10-
fcoalesce(\dots)
10+
fcoalesce(\dots, nan = NA)
1111
}
1212
\arguments{
1313
\item{\dots}{ A set of same-class vectors. These vectors can be supplied as separate arguments or as a single plain list, data.table or data.frame, see examples. }
14+
\item{nan}{ (numeric vectors only) Either \code{NaN} or \code{NA}; if \code{NaN}, then \code{NaN} is treated as distinct from \code{NA}, otherwise they are treated the same during replacement. }
1415
}
1516
\details{
1617
Factor type is supported only when the factor levels of each item are equal.
@@ -31,6 +32,9 @@ z = c(11L, NA, 1L, 14L, NA, NA)
3132
fcoalesce(x, y, z)
3233
fcoalesce(list(x,y,z)) # same
3334
fcoalesce(x, list(y,z)) # same
35+
x_num = c(NaN, NA_real_, 3.0)
36+
fcoalesce(x_num, 1) # default: NaN treated as missing -> c(1, 1, 3)
37+
fcoalesce(x_num, 1, nan=NaN) # preserve NaN -> c(NaN, 1, 3)
3438
}
3539
\keyword{ data }
3640

src/coalesce.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
- The replacement of NAs with non-NA values from subsequent vectors
77
- The conditional checks within parallelized loops
88
*/
9-
SEXP coalesce(SEXP x, SEXP inplaceArg) {
9+
SEXP coalesce(SEXP x, SEXP inplaceArg, SEXP nan_is_na_arg) {
1010
if (TYPEOF(x)!=VECSXP) internal_error(__func__, "input is list(...) at R level"); // # nocov
1111
if (!IS_TRUE_OR_FALSE(inplaceArg)) internal_error(__func__, "argument 'inplaceArg' must be TRUE or FALSE"); // # nocov
12+
if (!IS_TRUE_OR_FALSE(nan_is_na_arg)) internal_error(__func__, "argument 'nan_is_na_arg' must be TRUE or FALSE"); // # nocov
1213
const bool inplace = LOGICAL(inplaceArg)[0];
14+
const bool nan_is_na = LOGICAL(nan_is_na_arg)[0];
1315
const bool verbose = GetVerbose();
1416
int nprotect = 0;
1517
if (length(x)==0 || isNull(VECTOR_ELT(x,0))) return R_NilValue; // coalesce(NULL, "foo") return NULL even though character type mismatches type NULL
@@ -106,7 +108,7 @@ SEXP coalesce(SEXP x, SEXP inplaceArg) {
106108
SEXP item = VECTOR_ELT(x, j+off);
107109
if (length(item)==1) {
108110
double tt = REAL(item)[0];
109-
if (ISNAN(tt)) continue;
111+
if (nan_is_na ? ISNAN(tt) : ISNA(tt)) continue;
110112
finalVal = tt;
111113
break;
112114
}
@@ -116,9 +118,9 @@ SEXP coalesce(SEXP x, SEXP inplaceArg) {
116118
#pragma omp parallel for num_threads(getDTthreads(nrow, true))
117119
for (int i=0; i<nrow; ++i) {
118120
double val=xP[i];
119-
if (!ISNAN(val)) continue;
120-
int j=0; while (ISNAN(val) && j<k) val=((double *)valP[j++])[i];
121-
if (!ISNAN(val)) xP[i]=val; else if (final) xP[i]=finalVal;
121+
if (!(nan_is_na ? ISNAN(val) : ISNA(val))) continue;
122+
int j=0; while ((nan_is_na ? ISNAN(val) : ISNA(val)) && j<k) val=((double *)valP[j++])[i];
123+
if (!(nan_is_na ? ISNAN(val) : ISNA(val))) xP[i]=val; else if (final) xP[i]=finalVal;
122124
}
123125
}
124126
} break;

src/data.table.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ SEXP nafillR(SEXP obj, SEXP type, SEXP fill, SEXP nan_is_na_arg, SEXP inplace, S
251251
SEXP between(SEXP x, SEXP lower, SEXP upper, SEXP incbounds, SEXP NAbounds, SEXP check);
252252

253253
// coalesce.c
254-
SEXP coalesce(SEXP x, SEXP inplace);
254+
SEXP coalesce(SEXP x, SEXP inplace, SEXP nan_is_na_arg);
255255

256256
// utils.c
257257
bool within_int32_repres(double x);

0 commit comments

Comments
 (0)