Chapter 7 Loops and Conditionals

7.1 What is a loop?

  • Loops are automations that take care of repetitive tasks
    • Typically, we might go through data row by row and perform a task
  • Loops can have different forms:
    • for: loop over a pre-defined set of values, such as a number sequence
    • while: define constraints and keep loop running as long as they are met
    • repeat: loop repeats until broken (I do not recommend this ever!)
  • For is most common, while is nice for more advanced simulations

7.1.1 What are conditionals?

  • Conditionals define different actions for different conditions
  • They follow intuitive language:
    • if: define action to take when condition is met (logical)
    • else if: define action for another condition
    • else: define action for everything else
  • ifelse is the shortcut-function we already got to know for recoding with mutate()
    • defines exactly 1 condition, 1 action, 1 alternative
    • expandable version of ifelse is case_when

7.2 Exercise: What should I use?

  1. I want to print numbers from 1 to 7!
    • for loop (but realistically 1:7 ;) )
  2. I need to simulate more data as long as my sample size is smaller than 200!
    • while loop
  3. I want to print the age of only the females in my sample!
    • if/ else

7.3 for-loop

  • In a for loop, we need to define the range for which the loop should run
  • We define an iterating variable that will change each time the loop runs and take on all values of the defined range
    • Typically, we call this variable "i"
  • We define the range in round brackets and all actions the loop should take in curly brackets

7.3.1 Example

for(i in 1:4){
  print(paste("The iteration is", i))
}
# [1] "The iteration is 1"
# [1] "The iteration is 2"
# [1] "The iteration is 3"
# [1] "The iteration is 4"

7.3.2 Conditionals: If - else

if(variable == "value"){
  print("Do something")
} else if(variable == "other_value"){
  print("Do some other thing")
} else {
  print("Do anything else")
}

7.3.3 Conditionals: If - else

7.3.3.1 Checking numbers |

We want to test whether numbers in a loop are divisible by 3. If they are, we will display "Divisible by 3", and if not, we will simply output the iteration number like before.

For that we will use the modulo %% , which gives us the rest of a division. Let's try it out!

for(i in 1:4){
  if(i %% 3 == 0){
    print("Divisible by 3!")
  } else {
    print(i) 
  }
}
# [1] 1
# [1] 2
# [1] "Divisible by 3!"
# [1] 4

7.3.4 Exercise

Use a for-loop to display your favorite numbers. The numbers should be between 10 and 25.

If the number is divisible completely by 5, you should output "Divisible by 5!", if not please output the iteration number only.

for(i in 10:25){
  if(i %% 5 == 0){
    print("Divisible by 5!")
  } else {
    print(i) 
  }
}
# [1] "Divisible by 5!"
# [1] 11
# [1] 12
# [1] 13
# [1] 14
# [1] "Divisible by 5!"
# [1] 16
# [1] 17
# [1] 18
# [1] 19
# [1] "Divisible by 5!"
# [1] 21
# [1] 22
# [1] 23
# [1] 24
# [1] "Divisible by 5!"

7.4 Same function, different variables

for(i in c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")){
  print(mean(iris[ , i]))
}
# [1] 5.843333
# [1] 3.057333
# [1] 3.758
# [1] 1.199333


Brainteaser : What is the class() of i here?

character

7.4.1 More sophisticated

vector <- c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")

for(i in 1:length(vector)){
  print(paste("The mean value of", vector[i], "is", 
              round(mean(iris[ , vector[i]]), 2)))
}
# [1] "The mean value of Sepal.Length is 5.84"
# [1] "The mean value of Sepal.Width is 3.06"
# [1] "The mean value of Petal.Length is 3.76"
# [1] "The mean value of Petal.Width is 1.2"


Brainteaser : And what is the class() of i now?

integer (numeric)

7.4.2 With saving values

vector <- c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width")
means <- rep(NA, length(vector)) # create "empty" vector to fill

for(i in 1:length(vector)){
  print(paste("The mean value of", vector[i], "is", 
              round(mean(iris[ , vector[i]]), 2)))
  means[i] <- round(mean(iris[ , vector[i]]), 2)
}
# [1] "The mean value of Sepal.Length is 5.84"
# [1] "The mean value of Sepal.Width is 3.06"
# [1] "The mean value of Petal.Length is 3.76"
# [1] "The mean value of Petal.Width is 1.2"

7.4.3 Exercise: Seminar Data


Please download an edited version of our seminar data from ILIAS. You will find it under data as a zip folder. The dataset in it should have ".Rds" as a file ending. Read it in using:

seminar <- readRDS("./data/seminar_data.Rds")

Create a for-loop that saves the means of age, body height and technological skill from that seminar data in a vector named "seminar_means".

Hint: I renamed the variables to make them nicer to work with, so check out names(seminar)!

7.4.4 Solution

vector <- c("v02_age", "v04_bodyheight", "v05_skill_tech")
seminar_means <- rep(NA, length(vector)) # create "empty" vector to fill

for(i in 1:length(vector)){
  seminar_means[i] <- round(mean(seminar[ , vector[i]]), 2)
}

7.4.5 Checking What's Going On

7.4.5.1 browser()

  • In order to break our loop and enter a "debugging" mode, we can add browser() to any loop like so:
vector <- c("v02_age", "v04_bodyheight", "v05_skill_tech")
seminar_means <- rep(NA, length(vector)) # create "empty" vector to fill

for(i in 1:length(vector)){
  seminar_means[i] <- round(mean(seminar[ , vector[i]]), 2)
  browser()
}
  • The loop will run the first iteration until browser is called and then pause

  • It allows you to check in the console whether all variables look the way you want them to without having to wait for the loop to run

    • Or if there are errors/ warnings, you can check when they occur by moving the browser() to a different location in the code
  • To continue with the next iteration while in browser, type "c" into the console, "Q" to quit

    • The Esc key will also terminate the browser
  • Make sure you exit it before continuing with anything else

7.5 Loop with Conditional

In our seminar data, the average body height is 167.23 cm. We want to create a loop that goes through all rows (all seminar students) and outputs their height and whether it is above or below average.

What do we need for that?

7.5.1 Elements

  • For each person:
  • Check if their body height is above average
    • If yes: Output "This person is taller than average with ..."
    • Else: Output "This person is less tall than average with..."
  • Then paste the person's body height
  • Loop that over each person!
for(i in 1:nrow(seminar)){
  if(seminar$v04_bodyheight[i] > mean(seminar$v04_bodyheight)) {
    print(paste("This person is taller than average with", seminar$v04_bodyheight[i], "cm."))
  } else {
    print(paste("This person is less tall than average with", seminar$v04_bodyheight[i], "cm."))
  }
}
# [1] "This person is taller than average with 168 cm."
# [1] "This person is less tall than average with 160 cm."
# [1] "This person is taller than average with 171 cm."
# [1] "This person is less tall than average with 166 cm."
# [1] "This person is taller than average with 169 cm."
# [1] "This person is less tall than average with 164 cm."
# [1] "This person is less tall than average with 161 cm."
# [1] "This person is less tall than average with 166 cm."
# [1] "This person is taller than average with 183 cm."
# [1] "This person is taller than average with 172 cm."
# [1] "This person is less tall than average with 160 cm."
# [1] "This person is less tall than average with 164 cm."
# [1] "This person is taller than average with 170 cm."

7.5.2 And a more complicated outlook...

7.5.2.1 What happens here?

for(i in 1:nrow(seminar)){
  if(seminar$v11_soul[i] == "yes"){ # Check soul belief
    text1 <- "This person belives in the soul and"
  } else if (seminar$v11_soul[i] == "no") {
    text1 <- "This person does not belive in the soul and"
  } else { text1 <- "This person is unsure about the soul and" }
  
  if(seminar$v12_soul_phil[i] == "monism"){  # Check mind-body-philosophy
    text2 <- "believes the m-b-relationship is monistic."
  } else if (seminar$v12_soul_phil[i] == "dualism") {
    text2 <- "believes the m-b-relationship is dualistic."
  } else { text2 <- "is unsure of the m-b-relationship." }
  
  print(paste(text1, text2)) # Print text
}

7.5.3 Result

# [1] "This person belives in the soul and believes the m-b-relationship is dualistic."
# [1] "This person belives in the soul and is unsure of the m-b-relationship."
# [1] "This person belives in the soul and believes the m-b-relationship is monistic."
# [1] "This person is unsure about the soul and is unsure of the m-b-relationship."
# [1] "This person belives in the soul and is unsure of the m-b-relationship."
# [1] "This person does not belive in the soul and believes the m-b-relationship is monistic."
# [1] "This person is unsure about the soul and is unsure of the m-b-relationship."
# [1] "This person is unsure about the soul and is unsure of the m-b-relationship."
# [1] "This person does not belive in the soul and is unsure of the m-b-relationship."
# [1] "This person belives in the soul and believes the m-b-relationship is monistic."
# [1] "This person is unsure about the soul and believes the m-b-relationship is dualistic."
# [1] "This person belives in the soul and believes the m-b-relationship is dualistic."
# [1] "This person is unsure about the soul and is unsure of the m-b-relationship."

Wrap-Up & Further Resources

  • For-Loops must have a defined sequence to run over, e.g. 1 to 4
  • For-loops are the most common in R and are fit for most tasks
  • Loops are a powerful tool to e.g. easily perform the same task many times
  • Conditionals give you control over different operations depending on your data
  • In combination, loops and conditionals are most useful
  • Don't forget to play and create fun loops!


Lightbot

For Loop Meme
For Loop Meme
https://medium.com/nerd-for-tech/what-are-for-loops-b7215db28e83