Why does ifelse() return single-value output? [duplicate]

Those two functions should give similar results, don't they?

f1 <- function(x, y) {
   if (missing(y)) {
      out <- x
   } else {
      out <- c(x, y)
   }
   return(out)
}

f2 <- function(x, y) ifelse(missing(y), x, c(x, y))

Results:

> f1(1, 2)
[1] 1 2
> f2(1, 2)
[1] 1

This is not related to missing, but rather to your wrong use of ifelse. From help("ifelse"):

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.

The "shape" of your test is a length-one vector. Thus, a length-one vector is returned. ifelse is not just different syntax for if and else.


The same result occurs outside of the function:

> ifelse(FALSE, 1, c(1, 2))
[1] 1

The function ifelse is designed for use with vectorised arguments. It tests the first element of arg1, and if true returns the first element of arg2, if false the first element of arg3. In this case it ignores the trailing elements of arg3 and returns only the first element, which is equivalent to the TRUE value in this case, which is the confusing part. It is clearer what is going on with different arguments:

> ifelse(FALSE, 1, c(2, 3))
[1] 2

> ifelse(c(FALSE, FALSE), 1, c(2,3))
[1] 2 3

It is important to remember that everything (even length 1) is a vector in R, and that some functions deal with each element individually ('vectorised' functions) and some with the vector as a whole.