I'm trying to ensure I understand the different if
and else
options in R, they continually trip me up. There's lots of posts out there that discuss them, but I haven't seen a simple side by side comparison or explanation of all three. Can someone illustrate them for me?
Asked
Active
Viewed 41 times
0

mikemtnbikes
- 393
- 2
- 11
-
If you don't mind the feature creep, you could add in `case_when()` as another alternative approach to a similar problem. – Paul Stafford Allen Jul 17 '23 at 15:40
-
`if_else` is really an indexed choice function that operates on three vectors: one vector or expression that will evaluate to a logical vector and two item vectors . `if`{}else{}` returns a logical value with a single value as the “choice “ input and is used for programming choice, I.e. branching. `if_then` is an attempt to remove some of the infelicities of `ifthen`. – IRTFM Jul 17 '23 at 15:58
-
^I think you mean if_else and ifelse @IRTFM – Jon Spring Jul 17 '23 at 16:32
-
Yes. I’ll delete and re-comment when I get back to my desktop device with better keyboard. At the moment I’m all thumbs. – IRTFM Jul 17 '23 at 16:43
-
1So what is the question here? Stack Overflow is a question and answer site. If you want to answer your own question, you should post it as a proper "answer" below. This almost reads more like a blog post or article which is not what Stack Overflow is for. – MrFlick Jul 17 '23 at 16:57
-
1Also possible duplication of https://stackoverflow.com/questions/50646133/dplyr-if-else-vs-base-r-ifelse and https://stackoverflow.com/questions/22433704/difference-between-if-and-ifelse-functions or https://stackoverflow.com/questions/17252905/else-if-vs-ifelse. Not sure what is additionally beneficial here. – MrFlick Jul 17 '23 at 16:59
1 Answers
0
So to answer my own question
if(TEST) TRUE else FALSE
allows theTRUE
andFALSE
responses to take any class or form (unlikeif_else()
). It will not work ifTEST
is a vector unlikeifelse()
orif_else
ifelse(TEST, TRUE, FALSE)
is the vectorized version of 1). It will recycle theTRUE
andFALSE
values if necessary. I often get tripped up with it when I want to return a vector, in this case you need to use a list, e.g.- The command
ifelse(c(TRUE, FALSE), list(c("TRUE1a", "TRUE1b"), c("TRUE2a", "TRUE2b")), list(c("FALSE1a", "FALSE1b"), c("FALSE2a", "FALSE2b"))
- will return
list(c("TRUE1a", "TRUE1b"), c("FALSE2a", "FALSE2b"))
- The command
if_else()
requires the return values to be of the same type and will only recycle if a return value if it is of length 1.
Example Cases
Case 1: if() TRUE else FALSE
This is part of base
R
.
Its behavior is constrained by the fact that if() only works with scalars (i.e. vectors of length() == 1).
Unlike if_else() it doesn't check to see if the returned values are of the same type
## These both work
if(is.na(NA)) TRUE else FALSE
if(is.na(NA)) TRUE else "FALSE"
## if() TRUE else FALSE will does not work if the test has a length() > 1
##
## None of these work
if(is.na(c(NA, 1))) TRUE else FALSE
if(is.na(NA, 1)) TRUE else c(FALSE, FALSE)
if(is.na(c(NA, 1))) c(TRUE, TRUE) else c(TRUE, FALSE)
## However, if the test value has length() == 1, but return values
## have a length() > 1 it will still work.
## It just returns the appropriate value which happens to be a vector
## This behavior is consistent with this approach not checking that the return values are of the same type or length
if(is.na(NA)) c(TRUE, TRUE) else c(FALSE)
if(is.na(1)) c(TRUE, TRUE) else c(FALSE)
Case 2: ifelse()
This is a vectorized version of if() TRUE else FALSE and a base
function.
Similar to the scalar version in that it doesn't ensure the return values are
of the same type
## These both work
ifelse(is.na(NA), TRUE, FALSE)
## This works here, but doesn't work with `if_else`
ifelse(is.na(NA), TRUE, "FALSE")
## ifelse() will *work* (i.e. not throw an error) if the length of the return values
## is longer than the test vector. However, it has unexpected behavior in that
## it only returns the first value of the relevant vector. This is because the
## test value is only of length 1.
##
## These works but only returns the first element of the return values
## if() TRUE else FALSE would return the entire return value (i.e. a vector)
## if_else() would throw an error.
ifelse(is.na(NA), c(TRUE, TRUE, TRUE), FALSE)
ifelse(is.na(NA), c(TRUE, TRUE, TRUE), c(FALSE, FALSE))
## Unexpectedly (to me anyway) if for every element in the test vector there is
## a corresponding element return vector, it will return that element. I can see
## how this is consistent with R's default recycling behavior
##
## This works and returns the first and second elements of the TRUE vector
ifelse(is.na(c(NA, NA)), c(TRUE, NA), FALSE)
## This works and recycles the TRUE vector
ifelse(is.na(c(NA, 1)), TRUE, FALSE)
## This works as is a more complex illustration of recycling
ifelse(is.na(c(NA, NA, NA, NA)), c(TRUE, NA), FALSE)
Case 3: if_else()
This tidyverse
function requires both return variables to be of the same type
That's why it says it "Can't combine..." in the error message
## This works
if_else(is.na(NA), TRUE, FALSE)
## This doesn't
if_else(is.na(NA), TRUE, "FALSE")
## if_else() will recycle the TRUE and FALSE values based on the size of the TEST value
## However, it will only recycle the return values if it is of length 1. As a result, it won't work if the length of either return values is > 1, but < length(TEST).
##
## This works
if_else(is.na(c(NA, 1)), TRUE, FALSE)
## This does too, the TRUE case is recycled
if_else(is.na(c(NA, NA)), TRUE, c(FALSE, FALSE))
## This doesn't work since the TRUE cases is longer than the test cases
if_else(is.na(c(NA, 1)), c(TRUE, TRUE, TRUE), FALSE)

mikemtnbikes
- 393
- 2
- 11