为什么 R 的 ifelse 语句不能返回向量?

我发现 R 的 ifelse 语句有时非常方便,例如:

ifelse(TRUE,1,2)
# [1] 1
ifelse(FALSE,1,2)
# [1] 2

但我对下面的行为有些困惑。

ifelse(TRUE,c(1,2),c(3,4))
# [1] 1
ifelse(FALSE,c(1,2),c(3,4))
# [1] 3

这是一个超出我能力范围的设计选择吗?

50066 次浏览

ifelse的文件规定:

ifelse返回具有相同 形状为 test,其中填充 从 yesno取决于元素是否 testTRUEFALSE

因为要传递长度为1的测试值,所以要得到长度为1的结果。如果您通过了更长的测试向量,您将得到更长的结果:

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

因此,ifelse专门用于测试一个布尔值向量,并返回一个长度相同的向量,其中填充了从(向量) yesno参数获得的元素。

这是一个常见的混淆,因为函数的名称,使用这一点时,实际上你想只是一个普通的 if () {} else {}构造而不是。

是的,我认为 ifelse ()的设计就是为了当你有一个很长的测试向量,并且想要把每个测试映射到两个选项中的一个。例如,我经常这样为 plot ()设置颜色:

plot(x,y, col = ifelse(x>2,  'red', 'blue'))

如果你有一个很长的测试矢量,但想要输出对,你可以使用 sapply()plyrllply()或其他东西,也许。

我打赌你想要一个简单的 if语句而不是 ifelse-在 R 中,if不仅仅是一个控制流结构,它还可以返回一个值:

> if(TRUE) c(1,2) else c(3,4)
[1] 1 2
> if(FALSE) c(1,2) else c(3,4)
[1] 3 4

有时候用户只需要一个 switch语句而不是 ifelse语句:

condition <- TRUE
switch(2-condition, c(1, 2), c(3, 4))
#### [1] 1 2

(这是 Ken Williams 答案中的另一个语法选项)

注意,如果在 ifelse中分配结果,就可以避免这个问题:

ifelse(TRUE, a <- c(1,2), a <- c(3,4))
a
# [1] 1 2


ifelse(FALSE, a <- c(1,2), a <- c(3,4))
a
# [1] 3 4

这里有一个类似于 Cath 建议的方法,但是它可以与现有的预先分配的向量一起工作

它是基于这样使用 get():

a <- c(1,2)
b <- c(3,4)
get(ifelse(TRUE, "a", "b"))
# [1] 1 2

在您的案例中,使用 dplyr中的 if_else会很有帮助: if_elseifelse更严格,并且会为您的案例抛出一个错误:

library(dplyr)
if_else(TRUE,c(1,2),c(3,4))
#> `true` must be length 1 (length of `condition`), not 2

使用‘ if’,例如。

> `if`(T,1:3,2:4)
[1] 1 2 3

每滴血频道:

ifelse(rep(TRUE, length(c(1,2))), c(1,2),c(3,4))
#>[1] 1 2

可以复制条件的结果以返回所需的长度