R - 使用逻辑值进行switch语句

7

switch() 函数的第一个参数是一个表达式,它可以是数字或字符型字符串。

"EXPR 是一个求值结果为数字或字符型字符串的表达式。"

但是,它是否可以被强制转换为逻辑类型?如果可以,那么我在这段代码中是否做错了什么?

我有一个数据框中包含逻辑值的列,我想根据逻辑参数写一个新的列,其中包含数据框中现有数据的值:

exampleCurrent <- data.frame(value = c(5.5, 4.5, 4, 2.9, 2),
                         off = as.logical(c("F", "F", "T", "T", "F")),
                         extremeValue = as.logical(c("F", "F", "F", "F", "T")),
                         eclMinWork = c(5, 5.3, 5, 4.7, 3),
                         eclMinOff = c(4, 3.2, 3, 4, 3))

我希望能够达到以下目标:

我想要实现这个:

exampleWanted <- data.frame(value = c(5.5, 4.5, 4, 2.9, 2),
                        off = as.logical(c("F", "F", "T", "T", "F")),
                        extremeValue = as.logical(c("F", "F", "F", "F", "T")),
                        eclMinWork = c(5, 5.3, 5, 4.7, 4),
                        eclMinOff = c(4, 3.2, 3, 4, 3),
                        output = c(5, 4.5, 3, 2.9, 3))

选择数字的规则如下:
  1. 检查off。如果off为假,从valueeclMinWork中选择。如果off为真,则从valueeclMinOff中选择。
  2. 检查extremeValue。如果extremeValue为假,则选择步骤1中较小的数字。如果extremeValue为真,则选择步骤1中的数字。

我已经成功编写了一个执行这些操作的ifelse()函数,但我想知道是否可以使用switch代替。

exampleGenerated <- cbind(exampleCurrent, bestCase =
                          switch(exampleCurrent$off,
                                 FALSE = ifelse(exampleCurrent$value<exampleCurrent$eclMinWork,exampleCurrent$value, exampleCurrent$eclMinWork),
                                 TRUE = ifelse(exampleCurrent$value<exampleCurrent$eclMinOff,exampleCurrent$value, exampleCurrent$eclMinOff)))

上述代码抛出了一个错误,我认为是因为FALSE不是一个字符,并且从表面上看也不是数字或字符:

Error: unexpected '=' in: switch(exampleCurrent$off, FALSE ="

然而,我尝试使用as.numericas.character来包装变量,但也失败了。有没有方法可以做到这一点,还是我在代码中缺少了一个基本错误?


1
我认为即使你将其转换为字符,也无法在switch语句中传递一个ifelse语句。 - David Arenburg
@DavidArenburg,这可能是真的,但是如果我用一个直接的数值替换ifelse(),它仍然不起作用 :( - DaveRGP
1
请看这里 - David Arenburg
1
@DavidArenburg,如果我理解正确的话,您建议在“off”周围使用as.character,然后对false和true使用双引号。恐怕我仍然没有成功:exampleGenerated <- cbind(exampleCurrent, bestCase = switch(as.character(exampleCurrent$off), "FALSE" = "A", "TRUE" = "B")) - DaveRGP
2
这是因为 switch 不能接受长度大于1的向量(尝试阅读错误信息)。为了使你的示例正常工作,你需要循环它,即 sapply(exampleCurrent$off, function(x) switch(as.character(x), "FALSE" = "A", "TRUE" = "B"))。但我会选择 @Svens 的好方法。 - David Arenburg
显示剩余2条评论
1个回答

7

对于这个任务,您不需要使用switch。使用ifelsepmin更容易:

tmp <- with(exampleCurrent, ifelse(off, eclMinOff, eclMinWork))
transform(exampleCurrent, 
          bestCase = ifelse(extremeValue, tmp, pmin(value, tmp)))

#   value   off extremeValue eclMinWork eclMinOff bestCase
# 1   5.5 FALSE        FALSE        5.0       4.0      5.0
# 2   4.5 FALSE        FALSE        5.3       3.2      4.5
# 3   4.0  TRUE        FALSE        5.0       3.0      3.0
# 4   2.9  TRUE        FALSE        4.7       4.0      2.9
# 5   2.0 FALSE         TRUE        3.0       3.0      3.0

谢谢。这是意味着我不能使用switch(),还是只是不应该使用? - DaveRGP
1
@DaveRGP switch 无法进行向量化,因此您无法在此任务中使用它。 - Sven Hohenstein

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