Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

switch has problems with logical arguments

Apparently, switch has problems with logical arguments, and it can't evaluate on FALSE.

> switch(T, "TRUE"=10, "FALSE"=50)
[1] 10
> switch(F, "TRUE"=10, "FALSE"=50)
(No return value)

I know, for a T/F value I can use if/else but the problem with switch is a separate issue. It leads to even more weird things like

> switch(2, "TRUE"=10, "FALSE"=50, "2"=200)
[1] 50
> switch(2, "TRUE"=10, "FALSE"=50, 2=200)
Error: unexpected '=' in "switch(2, "TRUE"=10, "FALSE"=50, 2="
Error during wrapup: argument "fun" is missing, with no default

Why does this happen, and is it a bug or feature?

like image 396
highBandWidth Avatar asked Feb 21 '26 05:02

highBandWidth


1 Answers

?switch says

EXPR: an expression evaluating to a number or a character string

If you give it something else as EXPR, R will do the least invasive coercion possible to convert EXPR to a number or character string; in this case, the logical value gets converted to numeric. The problem is that when F/FALSE is coerced to numeric, it becomes 0, which selects none of the options. It's a hack, but you could use

a <- FALSE
switch(a+1, "FALSE"=10, "TRUE"=50)  ## 10
a <- TRUE
switch(a+1, "FALSE"=10, "TRUE"=50)  ## 50

... but you would have to remember to put the options in FALSE/TRUE order (the labels are ignored). I think this is A Bad Idea because it's tricky/non-obvious. The idiomatic R, I think, would be

if (a) 50 else 10

(this may seem too tricky, but is actually preferable to ifelse() for scalar comparisons; you could use ifelse() without losing much if you and your co-workers find it more readable)

In your second example (switch(2, "TRUE"=10, "FALSE"=50, "2"=200)), you gave switch() an integer so R selects by position (the second option has value 50). In your third example (switch(2, "TRUE"=10, "FALSE"=50, 2=200)), 2 is not a valid name for an argument.

like image 107
Ben Bolker Avatar answered Feb 22 '26 20:02

Ben Bolker