ifelse
returns a value with the same shape as
test
which is filled with elements selected
from either yes
or no
depending on whether the element of test
is TRUE
or FALSE
.
Usage
# S3 method for default
ifelse(test, yes, no)
Arguments
- test
an object which can be coerced to logical mode.
- yes
return values for true elements of
test
.- no
return values for false elements of
test
.
Value
A vector of the same length and attributes (including dimensions and
"class"
) as test
and data values from the values of
yes
or no
. The mode of the answer will be coerced from
logical to accommodate first any values taken from yes
and then
any values taken from no
.
Details
If yes
or no
are too short, their elements are recycled.
yes
will be evaluated if and only if any element of test
is true, and analogously for no
.
Missing values in test
give missing values in the result.
Examples
x <- c(6:-4)
sqrt(x) #- gives warning
#> Warning: NaNs produced
#> [1] 2.449490 2.236068 2.000000 1.732051 1.414214 1.000000 0.000000 NaN
#> [9] NaN NaN NaN
sqrt(ifelse(x >= 0, x, NA)) # no warning
#> [1] 2.449490 2.236068 2.000000 1.732051 1.414214 1.000000 0.000000 NA
#> [9] NA NA NA
## Note: the following also gives the warning !
ifelse(x >= 0, sqrt(x), NA)
#> Warning: NaNs produced
#> [1] 2.449490 2.236068 2.000000 1.732051 1.414214 1.000000 0.000000 NA
#> [9] NA NA 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:
#> [1] 11016 11045 11076 11106 11137 11167
class(y) <- class(x)
y
#> [1] "2000-02-29" "2000-03-29" "2000-04-29" "2000-05-29" "2000-06-29"
#> [6] "2000-07-29" "2000-08-29" "2000-09-29" "2000-10-29" "2000-11-29"
#> [11] "2000-12-29" "2001-01-29" NA "2001-03-29" "2001-04-29"
#> [16] "2001-05-29" "2001-06-29" "2001-07-29" "2001-08-29" "2001-09-29"
#> [21] "2001-10-29" "2001-11-29" "2001-12-29" "2002-01-29" NA
#> [26] "2002-03-29" "2002-04-29" "2002-05-29" "2002-06-29" "2002-07-29"
#> [31] "2002-08-29" "2002-09-29" "2002-10-29" "2002-11-29" "2002-12-29"
#> [36] "2003-01-29" NA "2003-03-29" "2003-04-29" "2003-05-29"
#> [41] "2003-06-29" "2003-07-29" "2003-08-29" "2003-09-29" "2003-10-29"
#> [46] "2003-11-29" "2003-12-29" "2004-01-29" "2004-02-29" "2004-03-29"
#> [51] "2004-04-29" "2004-05-29" "2004-06-29" "2004-07-29" "2004-08-29"
#> [56] "2004-09-29"
## This is a (not atypical) case where it is better *not* to use ifelse(),
## but rather the more efficient and still clear:
y2 <- x
y2[as.POSIXlt(x)$mday != 29] <- NA
## which gives the same as ifelse()+class() hack:
stopifnot(identical(y2, y))
## example of different return modes (and 'test' alone determining length):
yes <- 1:3
no <- pi^(1:4)
utils::str( ifelse(NA, yes, no) ) # logical, length 1
#> logi NA
utils::str( ifelse(TRUE, yes, no) ) # integer, length 1
#> int 1
utils::str( ifelse(FALSE, yes, no) ) # double, length 1
#> num 3.14