简体   繁体   中英

Why does ifelse convert a data.frame to a list: ifelse(TRUE, data.frame(1), 0)) != data.frame(1)?

I want to return a data.frame from a function if TRUE, else return NA using return(ifelse(condition, mydf, NA))

However, ifelse strips the column names from the data.frame.

Why are these results different?

> data.frame(1)
  X1
1  1
> ifelse(TRUE, data.frame(1), NA)
[[1]]
[1] 1

Some additional insight from dput():

> dput(ifelse(TRUE, data.frame(1), 0))
list(1)
> dput(data.frame(1))
structure(list(X1 = 1), .Names = "X1", row.names = c(NA, -1L), 
          class = "data.frame")

ifelse is generally intended for vectorized comparisons, and has side-effects such as these: as it says in ?ifelse ,

‘ifelse’ returns a value with the same shape as ‘test’ ...

so in this case ( test is a vector of length 1) it tries to convert the data frame to a 'vector' (list in this case) of length 1...

return(if (condition) mydf else NA)

As a general design point I try to return objects of the same structure no matter what, so I might prefer

if (!condition) mydf[] <- NA
return(mydf)

As a general rule, I find that R users (especially coming from other programming languages) start by using if exclusively, take a while to discover ifelse , then overuse it for a while, discovering later that you really want to use if in logical contexts. A similar thing happens with & and && .

See also:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM