为什么ifelse函数会将data.frame转换为list:ifelse(TRUE,data.frame(1),0)) != data.frame(1)?

27
我想从一个函数返回一个数据框,如果条件为TRUE,则返回该数据框,否则返回NA,使用return(ifelse(condition, mydf, NA))。然而,ifelse函数会从数据框中删除列名。为什么这些结果不同?
> data.frame(1)
  X1
1  1
> ifelse(TRUE, data.frame(1), NA)
[[1]]
[1] 1

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")
1个回答

32

ifelse通常用于向量化比较,并具有以下副作用:正如在?ifelse中所述,

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

所以在这种情况下(test是长度为1的向量),它试图将数据框转换为长度为1的“向量”(在此情况下为列表)...

return(if (condition) mydf else NA)

作为一般的设计原则,无论如何我都尽量返回相同结构的对象,所以我可能更喜欢。
if (!condition) mydf[] <- NA
return(mydf)

作为一般规则,我发现R用户(特别是来自其他编程语言的用户)开始时仅使用if,需要一段时间才能发现ifelse,然后在一段时间内过度使用它,最终发现在逻辑上真正想使用if。类似的事情也会发生在&&&上。
另请参见:
- Patrick Burns的R Inferno第3.2节... - 为什么R的ifelse语句不能返回向量?

@Ben 谢谢你的提示。我没有意识到 mydf[] <- NA 是一个选项。 - David LeBauer
@Ben,那么在后续的函数中,我是否应该将if(is.na(myfn()))的使用更改为if(sum(is.na(myfn()) >0)?如果需要澄清,我可以发布一个单独的问题。 - David LeBauer
1
可能只需要 if(all(is.na(mydf))) 吗? - Ben Bolker
或者使用 if(any(is.na(mydf))) 来匹配您之前的逻辑。 - Aaron left Stack Overflow
我认为最好返回一个空的数据框,而不是一个填充了缺失值的数据框。 - hadley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接