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

Posted

技术标签:

【中文标题】为啥 R 的 ifelse 语句不能返回向量?【英文标题】:Why can't R's ifelse statements return vectors?为什么 R 的 ifelse 语句不能返回向量? 【发布时间】:2010-11-23 01:52:21 【问题描述】:

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

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

【问题讨论】:

ifelse 的设计有点奇怪,因为 if else 很简单。 ifelse 是一个矢量化函数。它们应该用于不同的任务。 【参考方案1】:

ifelse 的文档指出:

ifelse 返回一个相同的值 形状为test 填充 从yesno 取决于元素是否 的testTRUEFALSE

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

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

因此,ifelse 旨在用于测试布尔向量并返回相同长度的向量,其中填充取自(向量)yesno 参数的元素。

这是一个常见的混淆,因为函数的名称,当你真的想要一个普通的if () else 构造时使用它。

【讨论】:

也许你真正想要的第二组语句是if (TRUE) c(1,2) else c(3,4)【参考方案2】:

我打赌你想要一个简单的 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

【讨论】:

@Ken,这对我有用,即使我得到了我需要的持续警告" Warning in if (req(inputval) == "All") : the condition has length > 1 and only the first element will be used" 我应该怎么做才能摆脱这个警告? @user5249203,问题和Ken的答案是指条件为单个值的情况,即长度为1的向量。警告表明req(inputval)有更多元素。要获得单个值,函数 any()all() 可能很有用。【参考方案3】:

请注意,如果您在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

【讨论】:

恕我直言,这是鼓励滥用矢量化 ifelse() 函数代替控制流 if ... else ... 进行分配。如果条件是单个TRUEFALSE 值,我更愿意写a &lt;- if (TRUE) c(1,2) else c(3,4)if (TRUE) a &lt;- c(1,2) else a &lt;- c(3,4) @Uwe 虽然我不认为使用 ifelse 而不是 if...else 在单一条件下的性能差异确实是一个问题,@987654332 @ 在某些情况下在代码中可能是首选(这里简单猜测),我不能不同意你;-)。我只是想通过ifelse 展示一种方式。 你也可以稍微滥用ifelselists - ifelse(TRUE, list(c(1,2)), list(c(3,4)) )[[1]]【参考方案4】:

使用`if`,例如

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

【讨论】:

这是这里唯一可以真正提供 ifelse 预期功能的答案。 有没有关于`if`的网址?【参考方案5】:

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

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

如果您有很长的测试向量,但想要输出对,您可以使用 sapply()plyrllply() 或其他东西。

【讨论】:

【参考方案6】:

有时用户只需要switch 语句而不是ifelse。在这种情况下:

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

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

【讨论】:

【参考方案7】:

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

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

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

【讨论】:

【参考方案8】:

在您的情况下,使用 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

【讨论】:

【参考方案9】:

发现于everydropr:

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

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

【讨论】:

以上是关于为啥 R 的 ifelse 语句不能返回向量?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能在使用 sort_by_key 对向量进行排序时使用返回引用的键函数?

为啥 Date 以“double”类型返回?

值的条件赋值 - ifelse() 当条件和预期的返回值没有相同的特征时是最好的吗? [R]

R:如何在向量上使用类似“if”的函数但没有“ifelse”,因为如果没有,它应该啥都不做

ifelse在向量的每个元素上

为啥可以从函数返回“向量”?