class: center, middle, inverse, title-slide .title[ # MACS 30500 LECTURE 9 ] .author[ ### Topics: Intro to Control Structures. Conditional Statements. ] --- class: inverse, middle # Agenda * What are Control Structures? Definition and Main Control Structures * Conditional Statements <!-- dropped vectors and lists from original version of this lecture and moved them to the data structure lecture; instead I added here conditional statements and more examples and content on iteration IDEA for next time: split this into two lecture 1: review data structure / base R + conditional statements (and add more in-class practice and how to do conditional statements with a dataframe, use penguins_clean!) lecture 2: loops slides and demo + loop exercises + maps/across + while loops. When you teach for loops add the break and continue statements (currently not in slides!) NB: in the demo for loop add data structure, e.g. show how to access columns of a df and their elements with the double and single square brakets --> --- class: inverse, middle ## What are Control Structures? --- ### Control Structures: Definition All code we have written so far can be seen as a finite and fixed sequence of commands. What's next? **Control structures allow us to change the flow of execution in our code. By incorporating logical conditions, they enable different lines of code to run based on the given conditions.** This approach differs from executing the same code in the same way each time, like we have done so far in this course! --- ### Main Control Structures * **Conditional statements**: test one or more condition(s) and act on it or them * **`for` loop**: execute a block of code for a fixed number of times * **`while` loop**: execute a block of code while a given condition is true, and stops only once the condition is evaluated as false -- *Today we focus on Conditional Statements and next on Loops!* <!-- We will now explain each of these control structures, and do practice exercises, but make sure to review the assigned readings for further details: one is from Chapter 13 “Control Structures” in *R programming for Data Science* and Chapter 21 “Iteration” in *R for Data Science* for details. --> --- class: inverse, middle ## Conditional Statements * single test with `if-else` * multiple tests with `if, else if, else` * nested conditionals * `ifelse()` or its tidyverse version `if_else()` **Download today's class materials and open the `warm-up.R` script** --- ### if-else if-else tests one condition and acts on it depending on whether the condition is TRUE or FALSE. Syntax: ``` if (condition to be evaluated) { action performed when condition is TRUE } else { action performed when condition is FALSE } ``` -- Example: ```r age <- 14 if (age > 16) { print("You can get a driving license") } else { print("You cannot drive") } ``` <!-- available options for size in descending order are: Huge > huge > LARGE > Large > large > normalsize > small > footnotesize > scriptsize > tiny --> --- ### if-else Example: What is the output of this code? ```r my_numbers <- c(3,4,5,"6",7) if (!is.numeric(my_numbers)) { print("At least one element is not numeric. Only provide numbers.") } else { print("All numeric elements") } ``` <!-- ``` ## [1] "At least one element is not numeric. Only provide numbers." ``` --> --- ### if, else if, else We can extend the basic if-else structure to test **multiple conditions!** How? by adding **`else if`** statement(s) between the initial `if` and the final `else` Syntax: ``` if (condition1) { # action performed when condition 1 is TRUE action1 } else if (condition2) { # action performed when condition 2 is TRUE action2 } else { # action performed when conditions 1 and 2 are FALSE action3 } ``` -- Conditional statements are evaluated **sequentially** (the order of your code matters!): * conditions are checked one-by-one in the order they are written * once R finds a TRUE condition, it stops, and the remaining conditions are not evaluated --- ### if, else if, else Example: check if a given number is positive, negative, or zero ```r x <- 0 if (x > 0) { print("x is a positive number") } else if (x < 0) { print("x is a negative number") } else { print("x is zero") } ``` --- ### if, else if, else Another Example with multiple `else if` statements: ```r # take user input temperature <- as.integer(readline(prompt = "Enter today's temperature in Celsius: ")) # determine weather based on temperature if (temperature >= 30) { weather <- "Hot" } else if (temperature >= 20) { weather <- "Cool" } else if (temperature >= 10) { weather <- "Breezy" } else { weather <- "Freezing!" } # print print(weather) ``` --- ### Nested if-else Use nested if-else statements to specify **conditions within conditions**. What does this code do? <!-- The %% modulo operator calculates the remainder from a division operation. Here 15 : 2 = 7, 1 is the reminder, thus the number is odd --> Example (the %% calculates the remainder from a division): .small[ ```r x <- 15 if (x > 0) { if (x %% 2 == 0) { print("x is a positive even number") } else { print("x is a positive odd number") } } else { if (x %% 2 == 0) { print("x is a negative even number") } else { print("x is a negative odd number") } } ``` ] --- ### Nested if-else Same example but this checks also the condition `x <- 0`: ```r x <- 0 if (x > 0) { if (x %% 2 == 0) { print("x is a positive even number") } else { print("x is a positive odd number") } } else if (x < 0) { if (x %% 2 == 0) { print("x is a negative even number") } else { print("x is a negative odd number") } } else { print("x is zero") } ``` --- ### ifelse() R accepts `if` and `else` statements, but also statements using **`ifelse()`**. They are not the same and **serve different purposes**. .small[ Syntax: ``` ifelse (condition to be evaluated, action performed when condition is TRUE, action performed when condition is FALSE) ``` Example: ```r y <- 3 ifelse(sqrt(16) > y, sqrt(16), 0) ``` ``` ## [1] 4 ``` ] <!-- if-else: more flexibile and handles complex conditional logic; returns a scalar ifelse(): simpler and more suited for simple assignments or to transform variables in a dataframe; returns a vector --> --- ### ifelse() Example: What is the output of this code? ```r numbers <- c(10, 6, 7) ifelse(numbers %% 2 == 1, "odd", "even") ``` -- ``` ## [1] "even" "even" "odd" ``` -- **Note the input here is a vector, not a single number, thus the output is also a vector**: the code will evaluate each element of the vector. This is because **`ifelse()` supports vectorized operations**: operations directly applied on entire vectors of data, rather than looping through individual elements one-by-one. <!-- How can we rewrite the same code using the standard `if-else` statement? ``` # won't work numbers <- c(10, 6, 7) if (numbers %% 2 == 1) { print("odd") } else { print("even") } ``` ``` # need a loop numbers <- c(10, 6, 7) for (i in 1:length(numbers)) { if (numbers[i] %% 2 == 1) { print("odd") } else print("even") } ``` --> --- ### ifelse() Example: What is the output of this code? ```r library(tidyverse) qualify <- tibble("Athlet" = c("Noah", "Julio", "Nick", "Maria"), "Scores" = c(32, 37, 28, 30)) ifelse(qualify$"Scores" > 30, "Admitted", "Rejected") ``` -- Example: What is the output of this code? ``` ## [1] "Admitted" "Admitted" "Rejected" "Rejected" ``` --- ### ifelse() Example: use `ifelse()` to recode variables in a dataframe... The variable `decisionDirection` takes four values (1 conservative, 2 liberal, 3 unspecifiable, and NA). Recode it to take three values (0 conservative, 1 liberal, and NA for both NA and unspecifiable) ```r scdb_case %>% mutate(decisionDirection = ifelse( decisionDirection == 3, # condition to be evaluated NA, # if true, do NA decisionDirection - 1 # if false, subtract one to value )) ``` <!-- More on this: https://docs.ycrc.yale.edu/r-novice-gapminder/07-control-flow/ Comparing ifelse() and for loop: https://www.r-bloggers.com/2020/02/if-else-and-ifelse/ --> --- ### if_else() Similarly to other functions we have seen, there is also a `dplyr` version of the base R `ifelse()` function and it is called `if_else()`. They follow the same logic, but the latter is better to use with the tidyverse Documentation here:https://dplyr.tidyverse.org/reference/if_else.html Compare the two! --- class: inverse, middle ## Practice writing conditional statements Download today's class materials from the website