NA
s, NaN
s, 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 NaN
s?
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 NaN
s.
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