NAs, NaNs, etc, in RR’s complex type (class) also supports missing values, i.e., NAs, and NaN (“Not a Number”) values as the numeric (double) is known for.
However, complex vectors (or matrices) are used much more rarely, and some details of R’s implementation have been unchanged since written in the early days of R (in the 90’s), even though they have not been quite consistent with the handling of NA and NaN for numeric objects.
First, note, e.g., from ? as.complex that R has a builtin for the “complex NA”,
NA_complex_
## [1] NA
whose purpose is to model complex missing values and which is equivalent to both real and imaginary part being NA:
identical(NA_complex_, complex(re = NA, im = NA))
## [1] TRUE
But what about complex NaNs?
They should be different from the above “complex NA”, but in R <= 3.3.2, you cannot use as.complex(NaN) to construct them, but e.g., complex(re = ., im = .)
cNaN <- complex(re = NaN, im = NaN)
c1NaN <- complex(re = 1, im = NaN); c(cNaN = cNaN, c1NaN = c1NaN)
## cNaN c1NaN
## NaN+NaNi 1+NaNi
Let’s use a small example vector to illustrate the behavior,
r <- c(NA,-1:2,NaN)
cc <- c(-NaN*(1+1i), NA + 1i*NaN,
complex(re=r, im=NaN),
complex(re=r, im= NA))
cc
## [1] NA NA NA -1+NaNi 0+NaNi 1+NaNi 2+NaNi
## [8] NaN+NaNi NA NA NA NA NA NA
Now already the printing is a bit surprising (if you know a bit more), or if you compare it with the following representation that reveals more about the internal structure:
(f.cc <- sapply(cc, deparse))
## [1] "NA_complex_" "NA_complex_"
## [3] "complex(real=NA, imaginary=NaN)" "complex(real=-1, imaginary=NaN)"
## [5] "complex(real=0, imaginary=NaN)" "complex(real=1, imaginary=NaN)"
## [7] "complex(real=2, imaginary=NaN)" "complex(real=NaN, imaginary=NaN)"
## [9] "NA_complex_" "complex(real=-1, imaginary=NA)"
## [11] "complex(real=0, imaginary=NA)" "complex(real=1, imaginary=NA)"
## [13] "complex(real=2, imaginary=NA)" "complex(real=NaN, imaginary=NA)"
names(cc) <- abbreviate(f.cc, minlength=11)
## all these are neither finite nor infinite :
stopifnot(!is.infinite(cc),
!is.finite(cc))
Now to the R interface, i.e., important ‘indicator’ functions such as is.na() which should be TRUE for all NA and NaN, or is.nan() which should be TRUE only for NaNs.
is.NA.c <- sapply(cc, function(.) identical(., NA_complex_))
ctab <- cbind(cc = format(cc), is.NA.c,
is.nan = is.nan(cc), is.na = is.na(cc),
duplic. = duplicated(cc), match. = match(cc,cc))
print(ctab, quote=FALSE, right=TRUE)
## cc is.NA.c is.nan is.na duplic. match.
## NA_complex_ NA TRUE FALSE TRUE FALSE 1
## NA_complex_ NA TRUE FALSE TRUE TRUE 1
## c(=NA,i=NN) NA FALSE TRUE TRUE FALSE 3
## c(=-1,i=NN) -1+NaNi FALSE TRUE TRUE FALSE 4
## cm(=0,i=NN) 0+NaNi FALSE TRUE TRUE FALSE 5
## cm(=1,i=NN) 1+NaNi FALSE TRUE TRUE TRUE 3
## cm(=2,i=NN) 2+NaNi FALSE TRUE TRUE FALSE 7
## c(=NN,i=NN) NaN+NaNi FALSE TRUE TRUE TRUE 7
## NA_complex_ NA TRUE FALSE TRUE TRUE 1
## c(=-1,i=NA) NA FALSE FALSE TRUE TRUE 1
## cm(=0,i=NA) NA FALSE FALSE TRUE FALSE 11
## cm(=1,i=NA) NA FALSE FALSE TRUE FALSE 12
## cm(=2,i=NA) NA FALSE FALSE TRUE FALSE 13
## c(=NN,i=NA) NA FALSE TRUE TRUE TRUE 3
Note that for R-devel, after 2015-09-22 (rev 69410), the above gives
## cc is.NA.c is.nan is.na duplic. match.
## c(=NN,i=NN) NaN+NaNi FALSE TRUE TRUE FALSE 1
## c(=NN,i=NN) NaN+NaNi FALSE TRUE TRUE TRUE 1
## c(=NA,i=NN) NA FALSE TRUE TRUE FALSE 3
## c(=-1,i=NN) -1+NaNi FALSE TRUE TRUE FALSE 4
## cm(=0,i=NN) 0+NaNi FALSE TRUE TRUE FALSE 5
## cm(=1,i=NN) 1+NaNi FALSE TRUE TRUE TRUE 3
## cm(=2,i=NN) 2+NaNi FALSE TRUE TRUE FALSE 7
## c(=NN,i=NN) NaN+NaNi FALSE TRUE TRUE TRUE 1
## NA_complex_ NA TRUE FALSE TRUE FALSE 9
## c(=-1,i=NA) NA FALSE FALSE TRUE TRUE 9
## cm(=0,i=NA) NA FALSE FALSE TRUE FALSE 11
## cm(=1,i=NA) NA FALSE FALSE TRUE FALSE 12
## cm(=2,i=NA) NA FALSE FALSE TRUE FALSE 13
## c(=NN,i=NA) NA FALSE TRUE TRUE TRUE 3
The last two columns are about match() and duplicated() — which are well consistent with unique(), but behave quite peculiarly (even after R-devel revision 69410):
stopifnot(identical(match(cc,cc) != seq_along(cc),
duplicated(cc)),
all.equal(unique(cc),
cc[!duplicated(cc)], # <- has names, hence :
check.attributes = FALSE))
and really they seem to behave wrongly, see the "duplic." column above, or also
which(duplicated(cc))
## [1] 2 6 8 9 10 14
and not much different in R-devel, after 2015-09-22 (rev 69410) :
## [1] 2 6 8 10 14
All the above was produced in the following R environment
sessionInfo()
## R version 3.2.2 (2015-08-14)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Fedora 22 (Twenty Two)
##
## locale:
## [1] LC_CTYPE=de_CH.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=de_CH.UTF-8
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=de_CH.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=de_CH.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] graphics grDevices datasets stats utils methods base
##
## other attached packages:
## [1] sfsmisc_1.0-29
##
## loaded via a namespace (and not attached):
## [1] magrittr_1.5 formatR_1.2.1 htmltools_0.2.6 tools_3.2.2
## [5] yaml_2.1.13 stringi_0.5-5 rmarkdown_0.8 knitr_1.11
## [9] stringr_1.0.0 digest_0.6.8 evaluate_0.8