How to write the first for loop in R

Martijn Theuwissen works or receives funding from a company or organization that would benefit from this article. Views expressed here are supported by a university or a company.

In this tutorial we will have a look at how you can write a basic for loop in R. It is aimed at beginners, and if you’re not yet familiar with the basic syntax of the R language we recommend you to first have a look at this introductory R tutorial.

Conceptually, a loop is a way to repeat a sequence of instructions under certain conditions. They allow you to automate parts of your code that are in need of repetition. Sounds weird? No worries, it will become more clear once we start working with some examples below.

Before you dive into writing loops in R, there is one important thing you should know. When surfing on the web you’ll often read that one should avoid making use of loops in R. Why? Well, that’s because R supports vectorization. Simply put, this allows for much faster calculations. For example, solutions that make use of loops are less efficient than vectorized solutions that make use of apply functions, such as lapply and sapply. It’s often better to use the latter. Nevertheless, as a beginner in R, it is good to have a basic understanding of loops and how to write them. If you want to learn more on the concepts of vectorization in R, this is a good read.

Writing a simple for loop in R

Let’s get back to the conceptual meaning of a loop. Suppose you want to do several printouts of the following form: The year is [year] where [year] is equal to 2010, 2011, up to 2015. You can do this as follows:

print(paste("The year is", 2010))
print(paste("The year is", 2011))
print(paste("The year is", 2012))
print(paste("The year is", 2013))
print(paste("The year is", 2014))
print(paste("The year is", 2015))
"The year is 2010"
"The year is 2011"
"The year is 2012"
"The year is 2013"
"The year is 2014"
"The year is 2015"

You immediately see this is rather tedious: you repeat the same code chunk over and over. This violates the DRY principle, known in every programming language: Don’t Repeat Yourself, at all cost. In this case, by making use of a for loop in R, you can automate the repetitive part:

for (year in c(2010,2011,2012,2013,2014,2015)){
  print(paste("The year is", year))
}
"The year is 2010"
"The year is 2011"
"The year is 2012"
"The year is 2013"
"The year is 2014"
"The year is 2015"

The best way to understand what is going on in the for loop, is by reading it as follows: “For each year that is in the sequence c(2010,2011,2012,2013,2014,2015) you execute the code chunk print(paste("The year is", year))”. Once the for loop has executed the code chunk for every year in the vector, the loop stops and goes to the first instruction after the loop block.

See how we did that? By using a for loop you only need to write down your code chunk once (instead of six times). The for loop then runs the statement once for each provided value (the different years we provided) and sets the variable (year in this case) to that value. You can even simplify the code even more: c(2010,2011,2012,2013,2014,2015) can also be written as 2010:2015; this creates the exact same sequence:

for (year in 2010:2015){
  print(paste("The year is", year))
}
"The year is 2010"
"The year is 2011"
"The year is 2012"
"The year is 2013"
"The year is 2014"
"The year is 2015"

As a last note on the for loop in R: in this case, we made use of the variable year but in fact, any variable could be used here. For example, you could have used i, a commonly-used variable in for loops that stands for index:

for (i in 2010:2015){
  print(paste("The year is", i))
}
"The year is 2010"
"The year is 2011"
"The year is 2012"
"The year is 2013"
"The year is 2014"
"The year is 2015"

This produces the exact same output. So you can really name the variable any way you want, but it’s just more understandable if you use meaningful names.

Using Next

Let’s have a look at a more mathematical example. Suppose you need to print all uneven numbers between 1 and 10 but even numbers should not be printed. In that case, your loop would look like this:

for (i in 1:10) {
  if (!i %% 2){
    next
  }
    print(i)
}
1
3
5
7
9

Notice the introduction of the next statement. Let’s explore the meaning of this statement walking through this loop together:

When i is between 1 and 10 we enter the loop and if not the loop stops. In case we enter the loop, we need to check if the value of i is uneven. If the value of i has a remainder of zero when divided by 2 (that’s why we use the modulus operand %%) we don’t enter the if statement, execute the print function and loop back. In case the remainder is non zero, the if statement evaluates to TRUE and we enter the conditional. Here we now see the next statement which causes to loop back to the i in 1:10 condition thereby ignoring the the instructions that follows (so the print(i)).

Closing remarks

In this short tutorial, you got acquainted with the for loop in R. While the usage of loops, in general, should be avoided in R, it still remains valuable to have this knowledge in your skillset. It helps you understand underlying principles, and when prototyping a loop solution is easy to code and read. In case you want to learn more on loops, you can always check this R tutorial.

10 Comments

  1. JY
    Josiah Yoder August 6, 2019

    Thanks for the quick introduction to loops in R. It certainly was handy.

    However, I’m not sure I agree with this statement:

    “Nevertheless, as a beginner in R, it is good to have a basic understanding of loops and how to write them.”

    As a programmer with a background in Python, Java, C++, etc., I have been programming in R for two months now before even thinking “Hey, maybe a loop would be good here”. And even in this case, I ended up replacing my loop with a vapply within the hour.

    Also, you may wish to say “odd numbers” instead of “uneven numbers,” unless you are wishing to emphasize the logical way you will reach them.

    Reply
  2. M
    Myhy May 15, 2019

    I think the explanations of the “next” usage must be reversed, in order to be correct:
    “If the value of i has a remainder of NON(my correction) zero when divided by 2 (that’s why we use the modulus operand %%) we don’t enter the if statement, execute the print function and loop back.”,In case the remainder is ZERO, the if statement evaluates to TRUE and we enter the conditional. Here we now see the next statement which causes to loop back to the i in 1:10 condition thereby ignoring the the instructions that follows (so the print(i))”. the scope is to print the even numbers, thus the False condition of the IF will be executed.

    Reply
  3. AP
    anik peimbert April 26, 2018

    hi! i what to save each year in a letter. For example if we have the code:
    for (i in 2010:2015){
    print(paste(“The year is”, i)) }

    instead of have as result
    “The year is 2010”
    “The year is 2011”
    “The year is 2012”
    “The year is 2013”
    “The year is 2014”
    “The year is 2015”

    have this
    a
    “The year is 2010”
    b
    “The year is 2011”
    c
    “The year is 2012”

    Reply
    1. D
      DWSWesVirginny May 8, 2018

      how about this? cat(paste(letters[1:6],”nThe year is”,2010:2015,’n’))

      Reply
      1. D
        denniericannnnn April 17, 2019

        How about this?

        T=50
        n=100
        mu=0
        sigma=1
        counter = 0

        #one realisation

        X = rnorm(T,mu,sigma)
        BM = rep(0,T)

        BM[1]=X[1]

        for(i in 2:T){
        BM[i]=BM[i-1]+X[i]
        }
        plot(BM, type = ‘l’)

        #for 100 realisations

        for (j in 1:n) {
        X = rnorm(T,mu,sigma)
        BM = rep(0,T)
        BM[1] = X[1]

        for(i in 2:T){
        BM[i] = BM[i-1] + X[i]
        }

        if (BM[T]>3){counter = counter + 1}

        }
        counter/n

        #——— Question 2 ——————————

        n=100
        T=60
        Y = rep(0,T+1)
        counter = 0

        #for occurrence
        Y[1] = 5
        posinc=c(-1,0,1)

        for (i in 2:T+1) {
        Y[i]= Y[i-1]+sample(posinc,1)
        }

        #for 100 occurrences

        for(j in 1:100){
        Y[1] = 5
        posinc=c(-1,0,1)
        for (i in 2:T+1) {
        Y[i]= Y[i-1]+sample(posinc,1)
        Y[i]= max(Y[i],0)
        }
        if(Y[T+1] < 10){counter = counter+1}
        }
        counter/n

        Reply
        1. U
          UYJRTDUYJ April 17, 2019

          n = 1e5
          T = 90

          Prac1B
          X = matrix(0,T,n)

          for (k in 1:n){
          posinc = c(2,2,2,1,0,0,0,-1,-1,-1)
          X[1,k] = 20+sample(posinc,1)
          }

          for (k in 1:n){
          for (j in 2:T){
          posinc = c(2,2,2,1,0,0,0,-1,-1,-1)
          X[j,k] = X[j-1,k]+sample(posinc,1)
          X[j,k] = max(X[j,k],0)
          }
          }

          mean((X[T,]>15)*(X[T,]<25))

          mean(X[60,])

          Reply
        2. A
          adam April 17, 2019

          prac1 q1

          T = 50
          n = 100
          mu = 0
          sigma = 1

          # time steps in BM
          BM = rep(0,T)
          n = 100
          count = 0
          #first loop is numer of realisations leae out for a single realisation
          for (i in 1:n){
          #have to define x in the first loop
          X = rnorm(T,mu,sigma)
          BM[1] = X[1]
          for (j in 2:T){
          #loop steps through BM adding x
          BM[j] = BM[j-1]+X[j]
          }
          #for the condition placed in question
          if (BM[T]>3) {count = count+1}
          }
          count/n

          q2 queue

          count=0
          n=100
          t=60
          #need to fill x with 0s to enter values into
          x=rep(0,t+1)
          #create a ector of values to be incemented at random with relative probaility
          posinc=c(-1,0,1)
          #create a loop for numer of repetitions (n)
          for ( i in 1:n)
          {
          #define how many people are in the queue to begin with
          x[1]=5
          #next loop for the different time steps
          for (j in 2:t+1)
          {
          #randomly choose from the vector which number should be incremented to 5
          inc=sample(posinc,1)
          x[j]=x[j-1]+inc
          x[j]=max(x[j],0)
          }
          #create the condition
          if (x[t+1]<10) {count=count+1}
          }
          count/n

          prac 2 compound poisson

          n=1000
          t=24
          lamda=20
          #create a vector full of 0s to add values
          y=rep(0,n)
          #create a loop to add values to the matrix
          for (i in 1:n)
          {
          nt=rpois(1,lamda*t)
          x=rexp(nt,1)
          y[i]=sum(x)
          }

          mean(y)
          var(y)

          Reply
          1. A
            adam April 17, 2019

            # ~~~~~~~~~~~~~~~~~~~~~~~~~ a ~~~~~~~~~~~~~~~~~~~~~~~~~
            install.packages(“expm”)
            library(expm)

            vect = c(0.6,0.3,0.4,0.7)
            P = matrix(vect,2,2)

            P%^%5

            P%^%10

            P%^%20

            # ~~~~~~~~~~~~~~~~~~~~~~~~~ b ~~~~~~~~~~~~~~~~~~~~~~~~~

            P5 = P%^%5
            P5[1,2]

            # ~~~~~~~~~~~~~~~~~~~~~~~~~ c ~~~~~~~~~~~~~~~~~~~~~~~~~

            P2 = P%^%2
            P3 = P%^%3
            P2[1,1]*P3[1,2]

            # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  4. PR
    Paul Rougieux December 8, 2015

    In his book “advanced R”, Hadley Wickham explains how to replace for loops by lapply (and its variants) to produce more readable code. He also explains that in some cases – modifying in place, recursive functions, while loops – it is preferable to keep using a loop: http://adv-r.had.co.nz/Functionals.html#functionals-loop

    Reply
  5. PR
    Paul Rougieux December 6, 2015

    This should be called how not to write a loop in R.

    paste(“The year is”,seq(2010,2015))

    Reply

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.