Chapter 6 Loops and Functions

In this chapter I want to introduce to a way to work more efficient. R is a programming language for statistical analysis, but it also includes classical elements of programming. Two main operations are loops and functions. We can automate tasks and the earlier you learn about it the faster you can advance and understand the logic of R. The goal of this chapter is to make you familiar with functions and loops so you know them when you see them.

6.1 Loops

For example, you can use a loop to iterate through a list of numbers and perform calculations on each number, or to go through the rows of a dataset and apply certain operations to each row. Loops provide a way to streamline your code and avoid writing repetitive instructions manually.

There are different type of Loops, but for this course we focus just on the for loops, since you will see them also in the QM Tutorial.

6.1.1 For loops

Do you remember my grade example from the first chapter?

grade <- 4.0

if (grade == 1.0) {
  print("Amazing") 
} else if (grade > 1.0 & grade <= 2.0) {
  print("Good Job")
} else if (grade > 2.0 & grade <= 3.0) {
  print("OK")
} else if (grade > 3.0 & grade <= 4.0) {
  print("Life goes on") 
}
## [1] "Life goes on"
grade <- 3.3

if (grade == 1.0) {
  print("Amazing") 
} else if (grade > 1.0 & grade <= 2.0) {
  print("Good Job")
} else if (grade > 2.0 & grade <= 3.0) {
  print("OK")
} else if (grade > 3.0 & grade <= 4.0) {
  print("Life goes on") 
}
## [1] "Life goes on"
grade <- 4.0

if (grade == 1.0) {
  print("Amazing") 
} else if (grade > 1.0 & grade <= 2.0) {
  print("Good Job")
} else if (grade > 2.0 & grade <= 3.0) {
  print("OK")
} else if (grade > 3.0 & grade <= 4.0) {
  print("Life goes on") 
}
## [1] "Life goes on"
grade <- 2.3

if (grade == 1.0) {
  print("Amazing") 
} else if (grade > 1.0 & grade <= 2.0) {
  print("Good Job")
} else if (grade > 2.0 & grade <= 3.0) {
  print("OK")
} else if (grade > 3.0 & grade <= 4.0) {
  print("Life goes on") 
}
## [1] "OK"
grade <- 1.7

if (grade == 1.0) {
  print("Amazing") 
} else if (grade > 1.0 & grade <= 2.0) {
  print("Good Job")
} else if (grade > 2.0 & grade <= 3.0) {
  print("OK")
} else if (grade > 3.0 & grade <= 4.0) {
  print("Life goes on") 
}
## [1] "Good Job"

I could now write down all my grades and assign them as I did in the first chapter, but there is a way to automatize this process. For that I will use the For loop.

First, let us make a vector with grades:

grades <- c(1.7, 3.3, 4.0, 2.3, 1.0)

Now, we can directly dive into the loop.

  • Write down for and in brackets you define the loop iterator, this is the i in the loop. Then you define in which object of interest you want to iterate. In our case, the operation should be iterated in the grades vector. I could also write down the number 5, but it is convention to define an object. Why?

  • After closing the brackets you open fancy brackets and write down your function, as you would normally, but this time you need to define how the iterator is used. Since I use the numbers in grades, my iterator needs to be put in brackets, after the name of the grades. Why?

  • And that’s it basically

for (i in 1:length(grades)) {
  if (grades[i] == 1.0) {
  print("Amazing") 
} else if (grades[i] > 1.0 & grades[i] <= 2.0) {
  print("Good Job")
} else if (grades[i] > 2.0 & grades[i] <= 3.0) {
  print("OK")
} else if (grades[i] > 3.0 & grades[i] <= 4.0) {
  print("Life goes on") 
}
  
}
## [1] "Good Job"
## [1] "Life goes on"
## [1] "Life goes on"
## [1] "OK"
## [1] "Amazing"

Loops can look differently:

In this example I have a number vector and my let the console print a sentence, where I vary the number and therefore the sentence changes over every loop

# creating num vector
num <- c(1, 2, 3, 4, 5, 249)

# looping through vector
for (i in num) { 
  print(stringr::str_c("This is the ", i, "th Iteration")) 
}
## [1] "This is the 1th Iteration"
## [1] "This is the 2th Iteration"
## [1] "This is the 3th Iteration"
## [1] "This is the 4th Iteration"
## [1] "This is the 5th Iteration"
## [1] "This is the 249th Iteration"

6.1.2 Nested Loops

Because you will eventually encounter them, I will show you shortly nested loops:

First, let us play a game of tic tac toe:

#Defining a matrix 
ttt <- matrix(c("X", "O", "X",
                "O", "X", "O",
                "O", "X", "O"), nrow = 3, ncol = 3, byrow = TRUE)

We define a loop with an iterator i for the rows of the matrix, and we define another one for the columns with the iterator j.

Afterwords, we built up the body, in which aim to get information about the matrix and its content. The sentence shows, which rows and columns contain which values.

for (i in 1:nrow(ttt)) {
  for (j in 1:ncol(ttt)) {
    print(paste("On row", i, "and column", 
                j, "the board contains", ttt[i,j]))
  }
}
## [1] "On row 1 and column 1 the board contains X"
## [1] "On row 1 and column 2 the board contains O"
## [1] "On row 1 and column 3 the board contains X"
## [1] "On row 2 and column 1 the board contains O"
## [1] "On row 2 and column 2 the board contains X"
## [1] "On row 2 and column 3 the board contains O"
## [1] "On row 3 and column 1 the board contains O"
## [1] "On row 3 and column 2 the board contains X"
## [1] "On row 3 and column 3 the board contains O"

6.2 apply() Function Family

6.2.1 apply()

apply() takes a data frame or matrix as an input and gives output in vector, list or array. Apply function in R is primarily used to avoid explicit uses of loop constructs. The idea is to apply a function repeatedly to a matrix or data frame: apply(X, MARGIN, FUNCTION)

#Let us create a matrix with random numbers 
mat <- matrix(1:10, nrow = 5, ncol = 6)

#Checking it
head(mat)
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    1    6    1    6    1    6
## [2,]    2    7    2    7    2    7
## [3,]    3    8    3    8    3    8
## [4,]    4    9    4    9    4    9
## [5,]    5   10    5   10    5   10

Assume you now want to calculate the mean of every column:

apply(mat, 2, mean) #calculating mean 
## [1] 3 8 3 8 3 8
apply(mat, 2, sum) #calculating sum
## [1] 15 40 15 40 15 40
apply(mat, 2, sd) #calculating sd
## [1] 1.581139 1.581139 1.581139 1.581139 1.581139 1.581139
#The corresponding Loop would look like this: 
for (i in 1:ncol(mat)) {
  mean_col <- mean(mat[, i])
  print(mean_col)
}
## [1] 3
## [1] 8
## [1] 3
## [1] 8
## [1] 3
## [1] 8

The apply() function is useful especially if you are working with dimensional bodies and want to calculate anything. However, they can not keep up with the flexibility of loops, you should be aware of that.

6.2.2 Notes

Loops and the apply function are widely used in programming. However, this is no programming course, it is an introduction, so now you have an idea what is happening, if you are seeing those two things in the scripts. But if you are interested in this topic, please read into while loops and repeat loops. The apply() function is part of a family: sapply(), lapply(), tapply() are also in that family.

6.3 Writing your own functions

We can again safe a lot of time and be more efficient by writing our own function.

  • First, you need to define a name for your function#
  • Afterwards, you write down the command with the function() command. In to your brackets you put your variables. Later your input follows those variables.
  • After the fancy brackets, you define your operation with your predefined variables.
  • Lastly, you want the function to return your quantity of interest and close the fancy brackets
  • Afterwards you have a function saved and can operate with it
#My function is just a sum

add <- function(x, y) { 
  
  result <- x + y
  return(result)
}

add(2,7) #Now I can use my function
## [1] 9

Let us calculate the area of a circle

aoc <- function(radius) {
  pi <- 3.14159
  
  area <- pi * radius^2
  
  return(area)
}

aoc(5)
## [1] 78.53975

Let us combine what we have learned in this chapter with a meeting of animals. You do not have to understand the code, and I also do not want to explain it, but just to make clear what loops and functions are able to do. And all packages are written based on functions and loops, so it is useful to get an overview how it could look like.

In this loop, we let R print out what persons in a classroom are doing. Before that we identify where the individuals are sitting. And the seating order in a class, is nothing more that a matrix right? We have rows and columns. This loops identifies in which row (i) and in which column (j) an individual sits. Moreover, the values in the matrix are student ids and the loop knows the id of students and prints out where which student sits. So this is an unnecessary loop, but I think a good example. Imagine the class are 1000 of people, then this loop would be necessary. As I said you do not need to completely understand it. Its purpose is to illustrate what you can do in R.

# The function
print_classroom <- function(x) {
  for (i in 1:length(x)) {  # Outer loop iterates over rows
    for (j in 1:length(x[[i]])) {  # Inner loop iterates over columns
      student <- x[[i]][j]
      if (student == 1) {
        comment <- "Alice"
      } else if (student == 2) {
        comment <- "Bob"
      } else if (student == 3) {
        comment <- "Cathy"
      } else if (student == 4) {
        comment <- "David"
      } else if (student == 5) {
        comment <- "Eva"
      } else {
        comment <- paste("Unknown student", student, "is doing something interesting.")
      }
      cat("At row", i, "column", j, ":", comment, "\n")
    }
  }
}

# Example usage
seating_order <- list(
  c(1, 5, 2),
  c(4, 3, 7)
)

#Checking it
print_classroom(seating_order)
## At row 1 column 1 : Alice 
## At row 1 column 2 : Eva 
## At row 1 column 3 : Bob 
## At row 2 column 1 : David 
## At row 2 column 2 : Cathy 
## At row 2 column 3 : Unknown student 7 is doing something interesting.

6.4 Outlook Loops and Functions

This course was a short introduction to automatize work and write efficient code: Loops and Functions. Since both concepts can get really complicated really fast, and in the beginning of your R-journey you will be less likely to use loops and functions. At some point however will you be confronted with loops and functions. And the earlier you see them, the better.

  • For further information on programming in R, I recommend “Hands-On Programming with R” by Garret Grolemund. In this book, the authors shows projects where he uses functions and loops, so it is a nice illustration of the usage of loops and functions.

6.5 Exercises Loops and Functions

6.5.1 Exercise 1: Writing a loop

Write a for loop that prints the square of each number from 1 to 10

#Assigning an object for a better workflow
number <- 10

#The Loop 

6.5.2 Exercise 2: Writing a function

Write a function that takes the input x and squares it:

#Defining a function for squaring

sq <- function (x) {
  
  
  
}

#Defining a vector containing a vector from 1 to 10 
numbers <- c(1:10) 

#Applying the number 
sq(numbers)

6.5.3 Exercise 3: The midnight Formula

This is the midnight formula separated in two equations:

\(x_{1,2} = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}\)

Make one function for the midnight formula, so the output are \(x_1\) and \(x_2\). Test it with a = 2, b = -6, c = -8

Hint: You need two split up the formula into two equations with two outputs.

mnf <- 


mnf(2, 6, 8)