How to Use the Switch Statement in R Functions

How to use the switch statement in R functions?

Well, switch probably wasn't really meant to work like this, but you can:

AA = 'foo'
switch(AA,
foo={
# case 'foo' here...
print('foo')
},
bar={
# case 'bar' here...
print('bar')
},
{
print('default')
}
)

...each case is an expression - usually just a simple thing, but here I use a curly-block so that you can stuff whatever code you want in there...

switch() statement usage

Well, timing to the rescue again. It seems switch is generally faster than if statements.
So that, and the fact that the code is shorter/neater with a switch statement leans in favor of switch:

# Simplified to only measure the overhead of switch vs if

test1 <- function(type) {
switch(type,
mean = 1,
median = 2,
trimmed = 3)
}

test2 <- function(type) {
if (type == "mean") 1
else if (type == "median") 2
else if (type == "trimmed") 3
}

system.time( for(i in 1:1e6) test1('mean') ) # 0.89 secs
system.time( for(i in 1:1e6) test2('mean') ) # 1.13 secs
system.time( for(i in 1:1e6) test1('trimmed') ) # 0.89 secs
system.time( for(i in 1:1e6) test2('trimmed') ) # 2.28 secs

Update With Joshua's comment in mind, I tried other ways to benchmark. The microbenchmark seems the best. ...and it shows similar timings:

> library(microbenchmark)
> microbenchmark(test1('mean'), test2('mean'), times=1e6)
Unit: nanoseconds
expr min lq median uq max
1 test1("mean") 709 771 864 951 16122411
2 test2("mean") 1007 1073 1147 1223 8012202

> microbenchmark(test1('trimmed'), test2('trimmed'), times=1e6)
Unit: nanoseconds
expr min lq median uq max
1 test1("trimmed") 733 792 843 944 60440833
2 test2("trimmed") 2022 2133 2203 2309 60814430

Final Update Here's showing how versatile switch is:

switch(type, case1=1, case2=, case3=2.5, 99)

This maps case2 and case3 to 2.5 and the (unnamed) default to 99. For more information, try ?switch

Switch function in R: how to throw an error message or default value when the input isn't matched?

You can add a default like this.

animal_sound <- function(x) {

switch(x,
"dog" = "woof",
"cat" = "meow",
"bee" = "bzzz",
"duck" = "quack",
"default")
}

R's switch statement is not a special form, is it therefore slow?

If you look at internal code of switch in file src/main/builtin.c, you can read in lines 1009-1025 :

This is a SPECIALSXP, so arguments need to be evaluated as needed.

SPECIALSXP means :

no  SEXPTYPE    Description
7 SPECIALSXP special functions

So switch is actually a special function which passes unevaluated arguments to the internal function.

Further reading the source code from line 1030 to line 1104 shows that as explained in ?switch, the function either handles character or number in a simple and not fully optimized way.

This probably explains why switch isn't particularly fast in situations which would for example require a binary search.

Use of switch() in R to replace vector values

The vectorised form of if is ifelse:

test <- ifelse(test == "He is", 1,
ifelse(test == "She is", 1,
ifelse(test == "He has", 2,
2)))

or

test <- ifelse(test %in% c("He is", "She is"), 1, 2)

switch is basically a way of writing nested if-else tests. You should think of if and switch as control flow statements, not as data transformation operators. You use them to control the execution of an algorithm, eg to test for convergence or to choose which execution path to take. You wouldn't use them to directly manipulate data in most circumstances.

Switch statement throws error

The more obvious way to get what you want is with time + 12.
It is simpler than switch and allows you to pass a vector and not just a value.

But as your problem might be more complicated than the one you put in your example and if you feel you need to use switch (for which you can pass only one value at a time), and to complete my comment, you have 2 options to do that, as stated in the below sample from help(switch):

switch works in two distinct ways depending whether the first argument
evaluates to a character string or a number.

If the value of EXPR is not a character string it is coerced to
integer. Note that this also happens for factors, with a warning, as
typically the character level is meant. If the integer is between 1
and nargs()-1 then the corresponding element of ... is evaluated and
the result returned: thus if the first argument is 3 then the fourth
argument is evaluated and returned.

If EXPR evaluates to a character string then that string is matched
(exactly) to the names of the elements in .... If there is a match
then that element is evaluated unless it is missing, in which case the
next non-missing element is evaluated, so for example switch("cc", a =
1, cc =, cd =, d = 2) evaluates to 2. If there is more than one match,
the first matching element is used. In the case of no match, if there
is a unnamed element of ... its value is returned. (If there is more
than one such argument an error is returned.)

Either time is a character variable:

time <- "3"
switch(time, "1"=13, "2"=14, "3"=15, "4"=16)
# [1] 15

Or time is numeric:

time <- 3
switch(time, 13, 14, 15, 16)
# [1] 15


Related Topics



Leave a reply



Submit