June 13, 2022

How to Use a For-Loop in R (with 18 Code Examples)

A for-loop is one of the main control-flow constructs in the R programming language. So what does that mean, and how do you use it?

In this tutorial, we will discuss what a for-loop in R is, what syntax it has, when it can be applied, how to use it on different data structures, how to nest several for-loops, and how we can regulate the execution of a for-loop.

What Is a For-Loop in R?

A for-loop is one of the main control-flow constructs of the R programming language. It is used to iterate over a collection of objects, such as a vector, a list, a matrix, or a dataframe, and apply the same set of operations on each item of a given data structure. We use for-loops to keep our code clean and avoid unnecessary repetition of a code block.

The basic syntax of a for-loop in R is the following:

for (variable in sequence) {
    expression
}

Here, sequence is a collection of objects (e.g., a vector) over which the for-loop iterates, variable is an item of that collection at each iteration, and expression in the body of the loop is a set of operations computed for each item.

From the syntax above, the keywords for and in are compulsory, as well as the parenthesis. The other elements, such as curly braces, indentation, placing the expression and the closing curly brace on a new line, the white space between the head and the body of a for-loop, are not compulsory yet strongly recommended. They are recommended for the purpose of highlighting the main parts of a for-loop and therefore improving the code readability and facilitating debugging (if necessary).

A for-loop stops after the last item of a collection of objects, unless the break statement is used (we will consider this statement later in this tutorial).

How to Use a For-Loop in R

Let's see how a for-loop in R can be used for iterating over various types of collections of objects. In particular, let's consider a vector, a list, and a matrix.

Using a For-Loop on a Vector

To start with a very simple example, let's print all the numbers from 1 to 5 inclusive. For this purpose, we will take the corresponding vector created with the : operator (1:5) and use the print() function as an expression:

for (x in 1:5) {
    print(x)
}
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5

In a real-world case, we may want to use a more meaningful variable name rather than x (e.g., price, month, etc.).

If we need to print each value as a character giving some more context, we can add the paste() function to the expression:

for (month in 1:5) {
    print(paste('Month:', month))
}
[1] "Month: 1"
[1] "Month: 2"
[1] "Month: 3"
[1] "Month: 4"
[1] "Month: 5"

Often, we need to evaluate a conditional expression in the for-loop body and based on that, output the corresponding result:

for (month in 1:5) {
    if (month < 3) {
        print(paste('Winter, month', month))
    } else {
        print(paste('Spring, month', month))
    }
}
[1] "Winter, month 1"
[1] "Winter, month 2"
[1] "Spring, month 3"
[1] "Spring, month 4"
[1] "Spring, month 5"

Using an easy-to-follow and consistent syntax, minding the indentation, and placing each part of the loop body on a new line, we clearly see that for the months 1 and 2 (i.e., less than 3), the for-loop prints "Winter" and the number of the month. For the other months, the for-loop prints outputs "Spring" and the number of the month. With the piece of code below, we effectively obtain the same result:

for(month in 1:5) if(month < 3)print(paste('Winter, month', month))else print(paste('Spring, month', month))
[1] "Winter, month 1"
[1] "Winter, month 2"
[1] "Spring, month 3"
[1] "Spring, month 4"
[1] "Spring, month 5"

In the second case, the code looks much more difficult to grasp. This confirms that using the right syntax, including non-compulsory elements, is important for better code readability.

We can store the output of a for-loop in a new vector by appending the result of each iteration to an initially empty vector, as in the example below:

vect_1 <- c(2, 7, 4, 9, 8)
vect_2 <- numeric()

for(num in vect_1) {
    vect_2 <- c(vect_2, num * 10)
}

vect_2
  1. 20
  2. 70
  3. 40
  4. 90
  5. 80

Above, we have multiplied each item of a numeric vector vect_1 by 10 and added the value from each iteration to vect_2.

A for-loop works also on character vectors:

animals <- c('koala', 'cat', 'dog', 'panda')

for (animal in animals) {
    print(animal)
}
[1] "koala"
[1] "cat"
[1] "dog"
[1] "panda"

Using a For-Loop on a List

Let’s try applying a for-loop on lists.

First, let's create a list with mixed data types and structures:

my_list <- list(c(5, 8, 2, 9), 'cat', 'dog', c('koala', 'panda', 'rabbit'), TRUE, 3.14)
my_list
    1. 5
    2. 8
    3. 2
    4. 9

  1. 'cat'
  2. 'dog'
    1. 'koala'
    2. 'panda'
    3. 'rabbit'
  • TRUE
  • 3.14
  • We can print the value of each item in the list:

    for (item in my_list) {
        print(item)
    }
    [1] 5 8 2 9
    [1] "cat"
    [1] "dog"
    [1] "koala"  "panda"  "rabbit"
    [1] TRUE
    [1] 3.14

    We can also print the length of each item in the list:

    for (item in my_list) {
        print(length(item))
    }
    [1] 4
    [1] 1
    [1] 1
    [1] 3
    [1] 1
    [1] 1

    Now, let's create a new list based on my_list with each item of the initial list replicated twice:

    my_list_2 <- list()
    
    for(i in 1:length(my_list)) {
        my_list_2[[i]] <- rep(my_list[[i]], 2)
    }
    
    my_list_2
      1. 5
      2. 8
      3. 2
      4. 9
      5. 5
      6. 8
      7. 2
      8. 9

      1. 'cat'
      2. 'cat'
      1. 'dog'
      2. 'dog'
    1. 'koala'
    2. 'panda'
    3. 'rabbit'
    4. 'koala'
    5. 'panda'
    6. 'rabbit'
    1. TRUE
    2. TRUE
    1. 3.14
    2. 3.14
  • As we did in the section on vectors, we can add a condition evaluation to the body of the for-loop above. Let's create a new list my_list_3, again based on my_list with each item of the initial list replicated twice, but only for the items with the length greater than 1. Otherwise, a character 'Too short item' will be added:

    my_list_3 <- list()
    
    for(i in 1:length(my_list)) {
        if (length(my_list[[i]]) > 1) {
            my_list_3[[i]] <- rep(my_list[[i]], 2)
        } else {
            my_list_3[[i]] <- 'Too short item'
        }
    }
    
    my_list_3
      1. 5
      2. 8
      3. 2
      4. 9
      5. 5
      6. 8
      7. 2
      8. 9

    1. 'Too short item'
    2. 'Too short item'
      1. 'koala'
      2. 'panda'
      3. 'rabbit'
      4. 'koala'
      5. 'panda'
      6. 'rabbit'
  • 'Too short item'
  • 'Too short item'
  • Using a For-Loop on a Matrix

    Since a matrix in R is a 2-dimensional data structure with rows and columns, to loop through a matrix, we have to use nested for-loops, i.e., one for-loop inside another for-loop:

    my_matrix <- matrix(1:9, nrow=3, ncol=3)
    
    for (row in 1:nrow(my_matrix)) {
        for (col in 1:ncol(my_matrix)) {
            print(paste('Row', row, 'col', col, 'value', my_matrix[row, col]))
        }
    }
    [1] "Row 1 col 1 value 1"
    [1] "Row 1 col 2 value 4"
    [1] "Row 1 col 3 value 7"
    [1] "Row 2 col 1 value 2"
    [1] "Row 2 col 2 value 5"
    [1] "Row 2 col 3 value 8"
    [1] "Row 3 col 1 value 3"
    [1] "Row 3 col 2 value 6"
    [1] "Row 3 col 3 value 9"

    In the above piece of code, we have created a 3x3 matrix, filled it with the integers from 1 to 9 inclusive, and used 2 nested for-loops to iterate over rows and columns, and print the value for each cell of the matrix.

    With nested for-loops, we can modify the values of a matrix. For example, let's reset all the values of our matrix to make each of them equal to the sum of the indices of the corresponding cell. For this purpose, we will use a built-in R function dim() that returns the dimension of a matrix:

    for(i in 1:dim(my_matrix)[1]) {
        for(j in 1:dim(my_matrix)[2]) {
            my_matrix[i, j] = i + j
        }
    }
    
    my_matrix
    2 3 4
    3 4 5
    4 5 6

    Nested for-loops in R are applicable not only for manipulating matrices. Below is a simple example on how to create various combinations of values of two vectors and print those combinations:

    qualities <- c('funny', 'cute', 'friendly')
    animals <- c('koala', 'cat', 'dog', 'panda')
    
    for (x in qualities) {
        for (y in animals) {
            print(paste(x, y))
        }
    }
    [1] "funny koala"
    [1] "funny cat"
    [1] "funny dog"
    [1] "funny panda"
    [1] "cute koala"
    [1] "cute cat"
    [1] "cute dog"
    [1] "cute panda"
    [1] "friendly koala"
    [1] "friendly cat"
    [1] "friendly dog"
    [1] "friendly panda"

    Using a For-Loop on a DataFrame

    Just in the same way as we did with the above matrix, we can loop through a dataframe, which is also a 2-dimensional data structure:

    super_sleepers <- data.frame(rating=1:4, 
                                 animal=c('koala', 'hedgehog', 'sloth', 'panda'), 
                                 country=c('Australia', 'Italy', 'Peru', 'China'),
                                 avg_sleep_hours=c(21, 18, 17, 10))
    
    print(super_sleepers)
      rating   animal   country avg_sleep_hours
    1      1    koala Australia              21
    2      2 hedgehog     Italy              18
    3      3    sloth      Peru              17
    4      4    panda     China              10
    for (row in 1:nrow(super_sleepers)) {
        for (col in 1:ncol(super_sleepers)) {
            print(paste('Row', row, 'col', col, 'value', super_sleepers[row, col]))
        }
    }
    [1] "Row 1 col 1 value 1"
    [1] "Row 1 col 2 value koala"
    [1] "Row 1 col 3 value Australia"
    [1] "Row 1 col 4 value 21"
    [1] "Row 2 col 1 value 2"
    [1] "Row 2 col 2 value hedgehog"
    [1] "Row 2 col 3 value Italy"
    [1] "Row 2 col 4 value 18"
    [1] "Row 3 col 1 value 3"
    [1] "Row 3 col 2 value sloth"
    [1] "Row 3 col 3 value Peru"
    [1] "Row 3 col 4 value 17"
    [1] "Row 4 col 1 value 4"
    [1] "Row 4 col 2 value panda"
    [1] "Row 4 col 3 value China"
    [1] "Row 4 col 4 value 10"

    Using the Break Statement Within a For-Loop

    The break statement is used inside a logical condition within a for-loop to exit the loop before it has iterated through all the items. In the case of nested loops, this statement results in interrupting the innermost loop only.

    Let's iterate through our character vector of animals from the previous example and stop the for-loop as soon as it encounters an item with less than 4 characters:

    animals <- c('koala', 'cat', 'dog', 'panda')
    
    for (animal in animals) {
        if (nchar(animal) < 4) {
            break
        }
        print(animal)
    }
    [1] "koala"

    We see that even though somewhere after "koala" we have another item with at least 4 characters ("panda") in our vector animals, the for-loop has not reached that value and stopped the execution at the first occurrence of an item with less than 4 characters ("cat").

    Using the Next Statement Within a For-Loop

    Unlike the break statement, this one is used for skipping an iteration based on certain predefined conditions rather than exiting the whole loop.

    To understand how this statement works, let's run the same piece of code as above substituting break with next:

    animals <- c('koala', 'cat', 'dog', 'panda')
    
    for (animal in animals) {
        if (nchar(animal) < 4) {
            next
        }
        print(animal)
    }
    [1] "koala"
    [1] "panda"

    This time, both items with less than 4 characters ("cat" and "dog") have been discarded while the other two ("koala" and "panda") have been printed.

    Conclusion

    In this tutorial, we have explored the usage of for-loops in R. Now we know the following:

    • How to define a for-loop in R
    • A for-loop's syntax — and which syntactic elements are compulsory
    • The purpose of a for-loop in R
    • How to use a for-loop on vectors, lists, and matrices
    • How and why to nest several for-loops
    • Which statements help regulate the behavior of a for-loop — and how to use them
    Elena Kosourova

    About the author

    Elena Kosourova

    Elena is a petroleum geologist and community manager at Dataquest. You can find her chatting online with data enthusiasts and writing tutorials on data science topics. Find her on LinkedIn.