-
Notifications
You must be signed in to change notification settings - Fork 0
/
readme.rmd
115 lines (86 loc) · 6.64 KB
/
readme.rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
---
title: "The switchcase package"
author: "Joachim Zuckarelli"
output: github_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
**New: switchcase tutorial on YouTube**
To learn more about the `switchcase` package and how it relates to R's buit-in primitive function `switch()` please watch the new `switchcase` tutorial on [YouTube](https://youtu.be/3ybF8u_PE7w).
# Introduction
In contrast to many other programming languages, R has no real native switch-case statement. It does provide the primitive `switch()` function; but `switch()` is actually made to select elements from a list based on their name or index position. It cannot (at least not without awkward workarounds) be used to build conditions with more complex comparison values. Also, when fed with a numeric expression, it interprets the expression as an index and selects the element from the list at this index position. This is not useful when you want to test an expression against another numeric expression/value.
It would be good to have an efficient way of testing multiple, similar conditions, including conditions that are more complex in their comparison values or result in numeric values. At the same time nested if-else constructs should be avoided because they make the code less clear and readable.
The `switchcase` package provides a solution by offering a true switch-case construct for R. It is encapsulated in the package's main function, `switchCase()`.
`switchCase()` allows to define multiple 'case' branches (alternatives) that consist of a condition and a code block that is executed if the condition is fulfilled. Also, it can be specified if the switch-case construct shall be left after one alternative code block has been executed, or if the other (following) conditions shall be tested, as well. This 'break' behavior can be defined on the level of the whole switch-case construct or on the level of each individual alternative, with the alternative's 'break' behavior setting overruling the construct-level option. Also, an alternative branch of a switch-case construct can return a value (which is then the return value of the `switchCase()` function).
# Installing `switchcase`
Before using `switchCase()` we need to install and load the package:
```
install.packages("switchcase", dependencies = TRUE)
```
```{r}
library(switchcase)
```
# Working with `switchcase`
To understand how the `switchCase()` function works, it makes sense to have a look at an example. In this simple example we are calculating the body-mass index of a person and then interpreting its value:
```{r cars}
bmi <- function(mass, size) {
ind <- mass / size^2
switchCase(
ind,
alt(
..expr <= 15,
{ cat("Your body mass index is ", ind, " which is very severely underweight.\n") },
"very severely underweight"
),
alt(
..expr > 15 & ..expr <= 16,
{ cat("Your body mass index is ", ind, " which is severely underweight.\n") },
"severely underweight"
),
alt(
..expr > 16 & ..expr <= 18.5,
{ cat("Your body mass index is ", ind, " which is underweight.\n") },
"underweight"
),
alt(
..expr > 18.5 & ..expr <= 25,
{ cat("Your body mass index is ", ind, " which is normal.\n") },
"normal"
),
alt(
..expr > 25 & ..expr <= 30,
{ cat("Your body mass index is ", ind, " which is overweight.\n") },
"overweight"
),
alt(
..expr > 30 & ..expr <= 35,
{ cat("Your body mass index is ", ind, " which is moderately obese.\n") },
"moderately obese"
),
alt(
..expr > 35 & ..expr <= 40,
{ cat("Your body mass index is ", ind, " which is severely obese.\n") },
"severly obese"
),
alt(
..expr > 40,
{ cat("Your body mass index is ", ind, " which is Very severely obese.\n") },
"very severly obese"
)
)
}
bmi.person1 <- bmi(82.5, 1.79)
cat("Person1 turned out to be ", bmi.person1)
```
Let us go through the call of `switchCase()` step by step:
The first argument is the value to be tested, in our case here the calculated body-mass index (variable `ind`).
This non-optional argument is followed by a set of alternative branches. The alternatives are built using the `alt()` function.
The `alt()` function takes a condition as its first argument. If you want to refer to the value that is tested in this switch-case construct then use the construct's standard variable `..expr` (yes, two dots!). In our example, `..expr` would take the value of ind. Working with `..expr` allwows you can build complex conditions for your alternative 'case' branches.
The second argument of `alt()` is the code that will be executed if the condition evaluates to `TRUE`. If your code has multiple R statements then put the statements in curly brackets. It is recommended to do that in any case. If an alternative has `NULL` as its code (i.e. the second argument of the `alt()` function is `NULL`) then this alternative is the default alternative that will be exceuted if no other condition evaluates to `TRUE`. If you define multiple defaults (which should be avoided, of course) then only the first one would be executed.
The optional third argument is the return value that the `switchCase()` function will provide if this particular 'case' alternative is executed. If multiple alternatives are executed (recall, that this is possible because the testing of alternative conditions does not necessarily need to stop after one condition has been found to be `TRUE`) then only the return value of the last alternative branch is returned.
The optional fourth argument of the `alt()` function (not used in this example) is a logical value indicating the 'break' behavior of this alternative branch. If set to `TRUE` then the execution of the switch-case construct will stop, regardless of the break option that has been defined on the construct level. The alternative's definition of the 'break' behavior always overrules the more general definition of 'break' behavior on the `switchCase()` function level.
The last and optional argument (break) of the `switchCase()` function (not used in this example) is a logical value indicating if the switch-case construct will be left after a condition was fulfilled and the R code associated with that 'case' branch has been executed. The default value for break is `TRUE`. Note, that this behavior specification can be overruled by the 'break' behavior specified in individual 'case' alternatives.
All code in the alternative 'case' branches is evaluated in the environment from which `switchCase()` was called so it is easy to access variables of your script or function in which `switchCase()` is used.
# Contact
Follow me on Twitter (https://twitter.com/jsugarelli) to stay up-to-date on new developement around the `switchcase` package.