+ - 0:00:00
Notes for current slide
Notes for next slide

Advanced R

Chapter 5: Control flow

Roberto Villegas-Diaz (@villegar)

2020-11-02

1 / 26

Overview

5.2 Choices

  • if ... else
  • if ... else if ... else
  • ifelse
  • switch

5.3 Loops

  • for
  • while
  • repeat
2 / 26

5.2 Choices

choices

if (condition) true_action
if (contition) true_action else false_action
3 / 26

5.2 Choices (2)

Test for N conditions

(Efficient way)

if (condition1) {
true_action1
} else if(condition2) {
true_action2
}
# ...
else if(conditionN) {
true_actionN
} else {
false_action
}

Test for N conditions

(don't do this, please)

if (condition1) {
true_action1
}
if(condition2) {
true_action2
}
# ...
if(conditionN) {
true_actionN
}
4 / 26

5.2 Choices (3)

Example: Grades

grade <- function(x) {
if (x >= 90) {
"A"
} else if (x >= 80) {
"B"
} else if (x >= 70) {
"C"
} else {
"F"
}
}
grade(99)
## [1] "A"
grade(50)
## [1] "F"
5 / 26

5.2 Choices (4)

5.2.1 Invalid inputs

"The condition should evaluate to a single TRUE or FALSE".

if ("x") 1
if (logical()) 1
if (NA) 1

Except, logical vectors of length > 1:

if (c(TRUE, TRUE, FALSE)) 1
6 / 26

5.2 Choices (5)

5.2.2 Vectorised if (aka ifelse)

x <- 1:5
ifelse(x %% 2 == 0, "even", "odd")
## [1] "odd" "even" "odd" "even" "odd"
7 / 26

5.2 Choices (5)

5.2.2 Vectorised if (aka ifelse)

x <- 1:5
ifelse(x %% 2 == 0, "even", "odd")
## [1] "odd" "even" "odd" "even" "odd"

Bonus: dplyr::case_when

dplyr::case_when(
x %% 2 == 0 ~ "even",
x %% 2 != 0 ~ "odd"
)
## [1] "odd" "even" "odd" "even" "odd"
8 / 26

5.2 Choices (6)

5.2.3 Fancy "if-chain" (aka switch)

x_option <- function(x) {
if (x == "a") {
"option 1"
} else if (x == "b") {
"option 2"
} else if (x == "c") {
"option 3"
} else {
stop("Invalid value")
}
}
x_option <- function(x) {
switch(x,
a = "option 1",
b = "option 2",
c = "option 3",
stop("Invalid value"))
}
legs <- function(x) {
switch(x,
cat = ,
dog = 4,
human = 2,
stop("Invalid value"))
}

If multiple inputs have the same output, the RHS can be empty.

9 / 26

5.2 Choices (7)

5.2.4 Exercises

  • What type of vector does each of the following calls to ifelse return?
ifelse(TRUE, "yes", "no")
ifelse(FALSE, "yes", "no")
ifelse(NA, "yes", "no")
  • Why does the following code work?
x <- 1:10
if (length(x)) "not empty" else "empty"
## [1] "not empty"
10 / 26

5.2 Choices (7)

5.2.4 Exercises

  • What type of vector does each of the following calls to ifelse return?
ifelse(TRUE, "yes", "no")
ifelse(FALSE, "yes", "no")
ifelse(NA, "yes", "no")
  • Why does the following code work?
x <- 1:10
if (length(x)) "not empty" else "empty"
## [1] "not empty"
x <- numeric()
if (length(x)) "not empty" else "empty"
## [1] "empty"
11 / 26

5.3 Loops

loops-meme

for (item in vector) perform_action
while(condition) action
repeat(action)
12 / 26

5.3 Loops (2)

for loops

for (i in 1:3) {
print(i)
}

Terminate loop:

  • next exists current iteration
for (i in 1:10) {
if (i %% 2 == 0)
next
print(i)
}
13 / 26

5.3 Loops (2)

for loops

for (i in 1:3) {
print(i)
}

Terminate loop:

  • next exists current iteration
for (i in 1:10) {
if (i %% 2 == 0)
next
print(i)
}
## [1] 1
## [1] 3
## [1] 5
## [1] 7
## [1] 9
14 / 26

5.3 Loops (3)

Terminate loop (cont.):

  • break exits the entire loop
for (i in 1:10) {
if (i %% 5 == 0)
break
print(i)
}
15 / 26

5.3 Loops (3)

Terminate loop (cont.):

  • break exits the entire loop
for (i in 1:10) {
if (i %% 5 == 0)
break
print(i)
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
16 / 26

5.3 Loops (4)

5.3.1 Common pitfalls

  • Preallocate the output container (performance)
means <- c(1, 50, 20)
out <- vector("list", length(means))
  • Instead of iterating over 1:length(x), use seq_along(x)
means <- c()
1:length(means)
## [1] 1 0
seq_along(means)
## integer(0)
17 / 26

5.3 Loops (5)

Flexibility: for < while < repeat

i <- 0
while (i < 10) {
i <- i + 1
if (i %% 2 == 0)
next
print(i)
}
## [1] 1
## [1] 3
## [1] 5
## [1] 7
## [1] 9
i <- 0
repeat({
i <- i + 1
if (i > 10) break
if (i %% 2 == 0) next
print(i)
})
## [1] 1
## [1] 3
## [1] 5
## [1] 7
## [1] 9
18 / 26

5.3 Loops (6)

5.3.3 Exercises

  • Why does this code succeed without errors or warnings?
x <- numeric()
out <- vector("list", length(x))
for (i in 1:length(x)) {
out[i] <- x[i] ^ 2
}
out
  • When the following code is evaluated, what can you say about the vector being iterated?
xs <- c(1, 2, 3)
for (x in xs) {
xs <- c(xs, x * 2)
}
xs
19 / 26

5.3 Loops (7)

5.3.3 Exercises

  • What does the following code tell you about when the index is updated?
for (i in 1:3) {
i <- i * 2
print(i)
}
20 / 26

Conclusion

Can we put these concepts together in diagram form? Let’s work on improving these schematics!

recap

21 / 26

Quiz

  • What is the difference between if and ifelse()?

  • In the following code, what will the value of y be if x is TRUE? What if x is FALSE? What if x is NA?

y <- if (x) 3

x = TRUE

if (TRUE) 3
## [1] 3
22 / 26

Quiz

  • What is the difference between if and ifelse()?

  • In the following code, what will the value of y be if x is TRUE? What if x is FALSE? What if x is NA?

y <- if (x) 3

x = TRUE

if (TRUE) 3
## [1] 3

x = FALSE

if (FALSE) 3
23 / 26

Quiz

  • What is the difference between if and ifelse()?

  • In the following code, what will the value of y be if x is TRUE? What if x is FALSE? What if x is NA?

y <- if (x) 3

x = TRUE

if (TRUE) 3
## [1] 3

x = FALSE

if (FALSE) 3

x = NA

if (NA) 3
24 / 26
  • What does switch("x", x =, y = 2, z = 3) return?
25 / 26
  • What does switch("x", x =, y = 2, z = 3) return?
    switch("x", x =, y = 2, z = 3)
## [1] 2
26 / 26

Overview

5.2 Choices

  • if ... else
  • if ... else if ... else
  • ifelse
  • switch

5.3 Loops

  • for
  • while
  • repeat
2 / 26
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
Esc Back to slideshow