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

Why can't R's ifelse statements return vectors?

提问人:Christopher DuBois 提问时间:8/27/2009 最后编辑:Gregor ThomasChristopher DuBois 更新时间:11/9/2020 访问量:53635

问:

我发现 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

这是一个高于我的工资等级的设计选择吗?

IF-语句 矢量化 R-FAQ

评论

2赞 2sb 6/29/2012
鉴于简单的if else工作,ifelse的设计有点奇怪。
5赞 marbel 1/11/2014
ifelse 是一个矢量化函数。它们应该用于不同的任务。

答:

126赞 Nathan Kitchen 8/27/2009 #1

各州的文档:ifelse

ifelse返回一个具有相同 形状,填充 从元素中选择的元素或取决于元素是否 的 是 或 。testyesnotestTRUEFALSE

由于您传递的是长度为 1 的测试值,因此您将获得长度为 1 的结果。如果通过更长的测试向量,将获得更长的结果:

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

So 用于测试布尔向量并返回相同长度的向量的特定目的,其中填充了从 (vector) 和参数中获取的元素。ifelseyesno

由于函数的名称,当您真的只想使用普通构造时,使用它是一种常见的混淆。if () {} else {}

评论

18赞 Jonathan Chang 8/27/2009
也许你真正想要的第二组语句是.if (TRUE) c(1,2) else c(3,4)
9赞 Brendan OConnor 8/29/2009 #2

是的,我认为 ifelse() 确实是为您有一个大的长测试向量并希望将每个测试映射到两个选项之一而设计的。例如,我经常以这种方式为 plot() 做颜色:

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

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

79赞 Ken Williams 11/19/2009 #3

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

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

评论

0赞 user5249203 1/6/2018
@Ken,这对我有用,即使我得到了我需要的持续警告,我应该怎么做才能摆脱这个警告?" Warning in if (req(inputval) == "All") { : the condition has length > 1 and only the first element will be used"
1赞 Uwe 7/20/2018
@user5249203,问题和 Ken 的答案指的是条件是单个值的情况,即长度为 1 的向量。警告指示具有更多元素。若要获取单个值,函数 or 可能有用。req(inputval)any()all()
4赞 agenis 7/8/2017 #4

有时,用户只需要一个语句,而不是一个 .在这种情况下:switchifelse

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

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

18赞 Cath 4/6/2018 #5

请注意,如果在以下位置分配结果,则可以规避该问题: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

评论

4赞 Uwe 7/20/2018
恕我直言,这鼓励滥用矢量化函数代替控制流进行分配。如果条件是单个或值,我更愿意写或ifelse()if ... else ...TRUEFALSEa <- if (TRUE) c(1,2) else c(3,4)if (TRUE) a <- c(1,2) else a <- c(3,4)
2赞 Cath 7/20/2018
@Uwe虽然我不认为使用时的性能差异......如果单个条件确实可能是一个问题,并且在某些情况下可能在代码中更受欢迎(这里简单猜测),我不能不同意你的看法;-)。我只是想用 .ifelseifelseifelseifelse
0赞 thelatemail 5/26/2021
你也可以稍微滥用和 s -ifelselistifelse(TRUE, list(c(1,2)), list(c(3,4)) )[[1]]
4赞 bmonger 7/26/2018 #6

这是一种类似于 Cath 建议的方法,但它可以与现有的预分配向量一起使用

它基于使用类似的东西:get()

a <- c(1,2)
b <- c(3,4)
get(ifelse(TRUE, "a", "b"))
# [1] 1 2
2赞 Matifou 5/21/2019 #7

在您的情况下,使用 from 会有所帮助: 比 更严格,并且会为您的情况抛出错误:if_elsedplyrif_elseifelse

library(dplyr)
if_else(TRUE,c(1,2),c(3,4))
#> `true` must be length 1 (length of `condition`), not 2
15赞 blueskyddd 7/7/2019 #8

使用“if”,例如

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

评论

1赞 sus_mlm 6/26/2020
这是这里唯一可以实际提供ifelse预期功能的答案。
0赞 Takuro Ikeda 2/10/2022
有没有关于“如果”的 URL?
0赞 blueskyddd 3/5/2022
@TakuroIkeda查看 adv-r.had.co.nz/Functions.html
0赞 SJGD 7/15/2020 #9

在每个dropr上找到:

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

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