ifelsereturns a value with the same shape as
testwhich is filled with elements selected from either
nodepending on whether the element of
ifelse(test, yes, no)
testand data values from the values of
no. The mode of the answer will be coerced from logical to accommodate first any values taken from
yesand then any values taken from
test(see the examples), and the class attribute (see
oldClass) of the result is taken from
testand may be inappropriate for the values selected from
no. Sometimes it is better to use a construction such as
(tmp <- yes; tmp[!test] <- no[!test]; tmp), possibly extended to handle missing values in
test. Further note that
if(test) yes else nois much more efficient and often much preferable to
ifelse(test, yes, no)whenever
testis a simple true/false result, i.e., when
length(test) == 1.
noare too short, their elements are recycled.
yeswill be evaluated if and only if any element of
testis true, and analogously for
Missing values in
test give missing values in the result.
x <- c(6:-4) sqrt(x) #- gives warning sqrt(ifelse(x >= 0, x, NA)) # no warning ## Note: the following also gives the warning ! ifelse(x >= 0, sqrt(x), NA) ## ifelse() strips attributes ## This is important when working with Dates and factors x <- seq(as.Date("2000-02-29"), as.Date("2004-10-04"), by = "1 month") ## has many "yyyy-mm-29", but a few "yyyy-03-01" in the non-leap years y <- ifelse(as.POSIXlt(x)$mday == 29, x, NA) head(y) # not what you expected ... ==> need restore the class attribute: class(y) <- class(x) y ## ==> Again a case where it is better *not* to use ifelse(), but ## both more efficient and clear: y2 <- x y2[as.POSIXlt(x)$mday != 29] <- NA stopifnot(identical(y2, y)) ## example of different return modes: yes <- 1:3 no <- pi^(0:3) typeof(ifelse(NA, yes, no)) # logical typeof(ifelse(TRUE, yes, no)) # integer typeof(ifelse(FALSE, yes, no)) # double