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