This post explains how to write and run for-loops in the R programming language.
The post will contain these content blocks:
1) Theoretical Workflow of for-Loops
2) Example 1: Loop Through Vector in R (Basics)
3) Example 2: Looping Over Character Vectors
4) Example 3: Store for-Loop Results in Vector by Appending
5) Example 4: Nested for-Loop in R
6) Example 5: Break for-Loop Based on Logical Condition
7) Example 6: Continue to Next Iteration of for-Loop
8) Example 7: for-Loop Over Data Frame Columns
9) Example 8: Create Variable Names Using for-Loop
10) Example 9: Creating Multiple Plots within for-Loop
11) Example 10: for-Loop Through List Object
12) Alternatives to for-Loops in R
Before we dive into the examples, let’s start with a quick theoretical introduction to for-loops…
Theoretical Workflow of for-Loops
I’ll first explain the workflow of for-loops. Have a look at the following graphic, it illustrates how for-loops work in theory:
At the beginning of each for-loop is a head that defines a collection of objects such as the elements of a vector or a list.
The head is followed by a code block (i.e. the body of our loop). In this block we can execute basically any R syntax we want.
Afterwards, the for-loop checks whether it reached the last object of the collection specified in the head of the loop. If this is the case, the for-loop is stopped. If this is not the case, the code block within the for-loop is repeated.
In the following, I’ll show you ten examples for the application of for-loops in R. So keep on reading!
Example 1: Loop Through Vector in R (Basics)
In this Example, I’ll illustrate how to use for-loops to loop over a vector.
In the following R code, we are specifying within the head of the for-loop that we want to run through a vector containing ten elements from the first element (i.e. 1) to the last element (i.e. 10).
Within the body of the for-loop we are then creating an output called x1, which contains the index of our loop to the power of 2. We are printing the result of our code block in each iteration to the RStudio console.
Let’s have a look at the R syntax and its output:
for(i in 1:10) { # Head of for-loop x1 <- i^2 # Code block print(x1) # Print results}# [1] 1# [1] 4# [1] 9# [1] 16# [1] 25# [1] 36# [1] 49# [1] 64# [1] 81# [1] 100
As you can see, the previous R code returned ten values, i.e. one value for each iteration.
Please have a look at this tutorial in case you want to learn more about for-loops and vectors in R.
Example 2: Looping Over Character Vectors
It is very important to understand that for-loops in R do not iterate over regular sequences, but over a collection of objects. For that reason, we are able to loop through vectors of character strings.
Let’s do an example in R! First, we have to create a character vector:
x2 <- c("Max", "Tina", "Lindsey", "Anton", "Sharon") # Create character vector
Now, we can loop over the elements of this character vector as shown below:
for(i in x2) { # Loop over character vector print(paste("The name", i, "consists of", nchar(i), "characters."))}# [1] "The name Max consists of 3 characters."# [1] "The name Tina consists of 4 characters."# [1] "The name Lindsey consists of 7 characters."# [1] "The name Anton consists of 5 characters."# [1] "The name Sharon consists of 6 characters."
If you want to learn more about loops and character vectors, you can have a look here.
Example 3: Store for-Loop Results in Vector by Appending
This Example shows how to concatenate the output of each for-loop iteration to a vector. For this task, we first have to create an empty vector:
x3 <- numeric() # Create empty data object
Now, we can use the for-statement to create a vector of output values:
for(i in 1:10) { # Head of for-loop x3 <- c(x3, i^2) # Code block}
Let’s print the results:
x3 # Print results# [1] 1 4 9 16 25 36 49 64 81 100
The resulting values are exactly the same as in the first example. However, this time we have saved the results in a vector object. You can learn more on this topic here.
Example 4: Nested for-Loop in R
for-loops are often used in nested loops. In Example 4, I’ll show how to nest a for-loop into another for-loop.
Let’s first create another empty vector (as in Example 3):
x4 <- character() # Create empty data object
Now, we can use the following nested for-loop to create a vector were each vector element contains two (different) letters of the alphabet:
for(i in 1:5) { # Head of first for-loop for(j in 1:3) { # Head of nested for-loop x4 <- c(x4, paste(LETTERS[i], letters[j], sep = "_")) # Code block }}
Let’s show the result:
x4 # Print results# "A_a" "A_b" "A_c" "B_a" "B_b" "B_c" "C_a" "C_b" "C_c" "D_a" "D_b" "D_c" "E_a" "E_b" "E_c"
The letter combinations are created on the basis of the index positions of our two nested for-loops. If you want to know more about nested loops in R, you might check out this tutorial.
Example 5: Break for-Loop Based on Logical Condition
It is possible to specify a logical if-condition within a for-loop that stops the execution of the loop in case it is TRUE.
This Example explains how to stop a loop when the if-condition i >=5 is fulfilled. For this, we have to use the break-statement within the if-condition:
for(i in 1:10) { # Head of for-loop x5 <- i^2 # Code block print(x5) # Print results if(i >= 5) { # Conditionally stop for-loop break # Using break-statement }}# [1] 1# [1] 4# [1] 9# [1] 16# [1] 25
As you can see based on the previous output of the RStudio console, our for-loop was stopped when the index i was equal to 5.
Example 6: Continue to Next Iteration of for-Loop
Similar to Example 5, we can also skip a for-loop iteration using the next-statement. The following for-loop is skipped at the index positions 1, 5, and 7:
for(i in 1:10) { # Head of for-loop if(i %in% c(1, 5, 7)) { # Conditionally skip iteration next # Using next-statement } x6 <- i^2 # Code block print(x6) # Print results}# [1] 4# [1] 9# [1] 16# [1] 36# [1] 64# [1] 81# [1] 100
Please have a look at this tutorial in case you want to learn more on skipping iterations within for-loops.
Example 7: for-Loop Over Data Frame Columns
In this Example, I’ll explain how to loop through the variables of a data frame. First, let’s load some example data:
data(iris) # Loading iris flower data sethead(iris) # Inspecting iris flower data set# Sepal.Length Sepal.Width Petal.Length Petal.Width Species# 1 5.1 3.5 1.4 0.2 setosa# 2 4.9 3.0 1.4 0.2 setosa# 3 4.7 3.2 1.3 0.2 setosa# 4 4.6 3.1 1.5 0.2 setosa# 5 5.0 3.6 1.4 0.2 setosa# 6 5.4 3.9 1.7 0.4 setosa
Our example data frame contains five columns consisting of information on iris flowers. Let’s also replicate our data in a new data frame object called iris_new1:
iris_new1 <- iris # Replicate iris data set
Now, we can loop over the columns of our data frame using the ncol function within the head of the for-statement. Within the for-loop, we are also using a logical if-condition:
for(i in 1:ncol(iris_new1)) { # Head of for-loop if(grepl("Width", colnames(iris_new1)[i])) { # Logical condition iris_new1[ , i] <- iris_new1[ , i] + 1000 # Code block }}
Let’s have a look at the updated data frame:
head(iris_new1) # Inspecting updated iris data# Sepal.Length Sepal.Width Petal.Length Petal.Width Species# 1 5.1 1003.5 1.4 1000.2 setosa# 2 4.9 1003.0 1.4 1000.2 setosa# 3 4.7 1003.2 1.3 1000.2 setosa# 4 4.6 1003.1 1.5 1000.2 setosa# 5 5.0 1003.6 1.4 1000.2 setosa# 6 5.4 1003.9 1.7 1000.4 setosa
As you can see, we have added +1000 to each column that contained the character pattern “Width”.
Check out this tutorial, if you want to learn more about the looping over data frame columns and rows.
Example 8: Create Variable Names Using for-Loop
In Example 8, I’ll show how to create or change variable names within a for-loop. Again, let’s replicate our original data frame:
iris_new2 <- iris # Replicate iris data set
Now, we can apply the colnames and paste0 functions to create new column names for each of our data frame columns:
for(i in 1:ncol(iris_new2)) { # Head of for-loop colnames(iris_new2)[i] <- paste0("new_", i) # Code block}
Let’s print the head of our updated data:
head(iris_new2) # Print updated data# new_1 new_2 new_3 new_4 new_5# 1 5.1 3.5 1.4 0.2 setosa# 2 4.9 3.0 1.4 0.2 setosa# 3 4.7 3.2 1.3 0.2 setosa# 4 4.6 3.1 1.5 0.2 setosa# 5 5.0 3.6 1.4 0.2 setosa# 6 5.4 3.9 1.7 0.4 setosa
As you can see, the columns of our data frame are named with the prefix “new_” and their position within the data frame. Click here, if you want to learn more on renaming variables within loops.
Example 9: Creating Multiple Plots within for-Loop
for-loops can be very handy when you want to draw multiple plots efficiently within a few lines of code. Let’s assume that we want to draw a plot of each numeric column of the iris data frame. Then, we can use the following R code:
for(i in 1:(ncol(iris) - 1)) { # Head of for-loop plot(1:nrow(iris), iris[ , i]) # Code block Sys.sleep(1) # Pause code execution}
The final plot created by the previous R code is shown in Figure 1. Note that we have specified to wait 1 sec after drawing a graph. This can also be useful when you want to create GIF-files.
I have created a more advanced tutorial on plotting data in for-loops. This tutorials also covers the ggplot2 package – a very powerful package for graphics in R.
Example 10: for-Loop Through List Object
In the previous examples we have applied for-loops to vectors and data frames. However, in this Example I’ll show how to write and use for-loops for the manipulation of list objects.
First, we have to create an example list:
my_list <- list(1:5, # Create example list letters[3:1], "XXX")my_list # Print example list# [[1]]# [1] 1 2 3 4 5# # [[2]]# [1] "c" "b" "a"# # [[3]]# [1] "XXX"
Our list consists of three different list elements. Now, we can use the length function to loop over our list:
for(i in 1:length(my_list)) { # Head of for-loop my_list[[i]] <- rep(my_list[[i]], 3) # Code block}
Let’s have a look at the output:
my_list # Print updated list# [[1]]# [1] 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5# # [[2]]# [1] "c" "b" "a" "c" "b" "a" "c" "b" "a"# # [[3]]# [1] "XXX" "XXX" "XXX"
As you can see, we have replicated each list element three times.
More on this topic can be found here.
Alternatives to for-Loops in R
As you have seen in this article, for-loops are a beautiful weapon of the R programming language.
However, a big drawback of for-loops can be their computation time when they are not applied properly. When applied to large data sets they can be very time consuming; sometimes they might even crash R entirely.
In order to write efficient for-loops, certain guidelines should be considered. Please have a look at the article by Uwe Ligges and John Fox in this publication for a detailed discussion on the performance of loops in R.
If you want to avoid for-loops in your R code instead, you may have a look at this tutorial in case you want to learn more about alternatives such as the lapply or map functions.
Video & Further Resources
Do you need more explanations on the content of the present article? Then you might want to watch the following video of my YouTube channel. In the video, I illustrate the examples of this article in RStudio:
The YouTube video will be added soon.
In addition, I can recommend to have a look at the other articles of my website. Especially, you may have a look at my overview article on loops in R. It lists all related tutorials on loops, statements, and user-defined functions:
- Overview Page About Loops in R
Also, please have a look at my tutorials on while- and repeat-loops – the two other types of loops provided by the R programming language. Depending on your specific data situation, one of these loop-types may be better suited for you:
- while-Loop in R
- repeat-Loop in R
In summary: In this article you learned how to apply for-loops in different settings in the R programming language. In case you have additional comments or questions, don’t hesitate to let me know in the comments section.
17 Comments. Leave new
Wang
July 6, 2022 1:40 am
ReplyHi Joachim,
Thank you for the great content. I have a question about looping or whether it can be done using another command. I have a dataset with 1000 observations and 10 columns. It is on the diet pattern of students. It looks sth like this. if the student has eaten, it is coded a 1 and 0 for not. Now, I want to identify: no of the students who have eaten only apple, only banana, only Mango, apple and banana, apple and Mango, banana and Mango, all three fruits.
id. apple banana Mango
1. 1 0 0
2. 0 1 1
3. 1 0 0
4. 0 1 1
5. 1 1 0Joachim
July 8, 2022 6:57 pm
ReplyHey Wang,
Thank you for the kind comment, and the interesting question!
I have tried to reproduce your problem:
set.seed(472764)data <- data.frame(id = 1:50, apple = rbinom(50, 1, 0.3), banana = rbinom(50, 1, 0.3), mango = rbinom(50, 1, 0.3))head(data)# id apple banana mango# 1 1 0 0 0# 2 2 0 0 1# 3 3 1 0 0# 4 4 1 0 0# 5 5 0 1 1# 6 6 0 0 0nrow(data[data$apple == 1 & data$banana == 0 & data$mango == 0, ]) # Only applenrow(data[data$apple == 0 & data$banana == 1 & data$mango == 0, ]) # Only banananrow(data[data$apple == 0 & data$banana == 0 & data$mango == 1, ]) # Only mangonrow(data[data$apple == 1 & data$banana == 1 & data$mango == 0, ]) # Apple & banananrow(data[data$apple == 1 & data$banana == 0 & data$mango == 1, ]) # Apple & mangonrow(data[data$apple == 0 & data$banana == 1 & data$mango == 1, ]) # Banana & mangonrow(data[data$apple == 1 & data$banana == 1 & data$mango == 1, ]) # All fruitsnrow(data[data$apple == 0 & data$banana == 0 & data$mango == 0, ]) # No fruits
The code above returns the desired results without using a for-loop. In case you have more combinations, you might try to make this code more efficient (for example using the expand.grid function).
I hope that helps!
Joachim
Constanze
September 30, 2022 12:31 pm
ReplyHi Joachim,
I am trying to use a loop to conditionally replace some values in a data frame column.
My data frame has 4 columns and starts like this:
print(data)
Correlation N Cor_type vi
1 0.07 1292 Pearson 0.0008
2 0.07 280 Pearson 0.0036
3 0.12 672 Pearson 0.0015
4 0.03 340 Pearson 0.0030
5 0.04 155 Pearson 0.0066
6 0.04 155 Pearson 0.0066
7 -0.08 374 Spearman 0.0027
8 -0.04 14 Spearman 0.0909
9 -0.11 166 Spearman 0.0061
10 -0.01 194 Spearman 0.0052
(…)Now, I want to change the values for vi to 1/(data$N – 3) for rows with Cor_type == “Spearman” (keeping the original values for vi in all other rows). I have tried different ways to write a loop for this but cannot get it to work. I would really appreciate if you could help me with this, thanks in advance.
Joachim
September 30, 2022 6:01 pm
ReplyHi Constanze,
Please have a look at my response to your other comment.
Regards,
Joachim
Constanze
September 30, 2022 12:37 pm
One small correction, 1/(data$N – 3) is the formula used to create the current values of vi, for the new values the formula that should be used is 1.06/(data$N – 3).
ReplyJoachim
September 30, 2022 6:02 pm
ReplyHi again,
You don’t need a for-loop for this. You could replace those values conditionally as demonstrated in the following example:
data <- data.frame(Correlation = c(0.07, 0.07, 0.12, 0.03), N = c(1292, 280, 672, 340), Cor_type = c("Pearson", "Spearman", "Pearson", "Spearman"), vi = c(0.0008, 0.0036, 0.0015, 0.0030))data# Correlation N Cor_type vi# 1 0.07 1292 Pearson 0.0008# 2 0.07 280 Spearman 0.0036# 3 0.12 672 Pearson 0.0015# 4 0.03 340 Spearman 0.0030data$vi[data$Cor_type == "Spearman"] <- 1.06/(data$N[data$Cor_type == "Spearman"] - 3)data# Correlation N Cor_type vi# 1 0.07 1292 Pearson 0.000800000# 2 0.07 280 Spearman 0.003826715# 3 0.12 672 Pearson 0.001500000# 4 0.03 340 Spearman 0.003145401
I hope this helps!
Joachim
Constanze
October 4, 2022 4:00 pm
ReplyHi Joachim,
Thank you so much for your help! This is what I was trying to achieve.
Constanze
Joachim
October 5, 2022 9:04 am
ReplyHi Constanze,
This is great to hear, glad it helped!
Regards,
Joachim
Atinga David
October 10, 2022 4:04 am
ReplyHi Joachim,
Regards for the content and uploaded videos. I have a question about “Looping Over Data Frame Rows”, I am a beginner in R and now learning how to loop. I imported my time series data from stata to r and below is the data view of the first six rows.
Plot_id = 1 – 872
Year = 1982 – 2021 (for each Plot_id)
Month = 1 – 12 (for each Year)# Plot_id Year Month prcp Tmax Tmin
#
# 1 1 1982 1 0.262 32.1 15.1
# 2 1 1982 2 5.16 32.7 18.9
# 3 1 1982 3 44.9 33.0 21.7
# 4 1 1982 4 142. 32.1 23.6
# 5 1 1982 5 99.6 30.7 23.1
# 6 1 1982 6 102. 29.4 22.4What I want to do?
Do some analysis (calculate SPI & SPEI index) based on each Plot_id.# Loaded needed packages
library(SPEI)
library(haven)
library(dplyr)# Importing data
Data <- read_dta("C:/Users/DAVID/Desktop/test1/SPEI ready data/Data.dta")
View(Data)# (a) calculating SPI by trying to loop
# *******************************Data<- for(i in Plot_id) {
spi3<-spi(Data$prcp,3)
plot.spei(spi3)
spi3
}Error: "Error in Plot_id : object 'Plot_id' not found"
# (B) calculating SPEI (using Hargreaves method) by trying to loop
# ******************************************************Data<- for(i in Plot_id) {
# Calculating PET (Potential Evapo-transpiration)
Data$PET<-hargreaves(Tmin=Data$Tmin, Tmax = Data$Tmax, lat=9.37)
Data$PET# Calculating the climatic water balance (CWBal) for SPEI
CWBal<-Data$prcp-Data$PET# calculating SPEI index
spei6<-spei(CWBal,6)
spei6}
I am able to do the analysis when I save the data based on each Plot_id but its a lot of work for 872 plots.
Joachim
November 14, 2022 11:56 am
ReplyHey Atinga,
Please excuse the late response. I was on a long holiday so unfortunately I wasn’t able to reply sooner. Still need help with your code?
Regards,
Joachim
Atinga David
November 14, 2022 12:27 pm
Yes I do, went through the long route and looping will save me great deal of time in my subsequent research.
ReplyJoachim
November 15, 2022 10:57 am
ReplyHey Atinga,
I think one problem of your loop is that the name of the data set is missing in front of the column name Plot_id.
Another problem is that you shouldn’t assign the for-loop to a new data object.
Please try the following code (note the Data$ in front of Plot_id):
for(i in Data$Plot_id) {spi3<-spi(Data$prcp,3)plot.spei(spi3)spi3}
I hope that helps!
Joachim
soue
February 5, 2023 9:32 am
ReplyHi Joachim,
Thanks for all your valuable content.
I need to solve this equation system for my 258 lines:
for (i in 1:258)
result<-solve(matrix(c((PTF[i,2]),1,(PTF[i,3]),1),nrow=2), matrix(c((PTF[i,1]),1),nrow=2))But R, gave me the last result, only for the 258 line. I would really appreciate if you could help me. Thank you in advance.
soue
February 5, 2023 5:28 pm
solved. Thank you 🙂
ReplyCansu (Statistics Globe)
February 6, 2023 9:34 am
ReplyHello Soue,
Thank you for the update, you can always contact us for further help.
Regards,
Cansu
Jeff Norriss
March 20, 2023 3:55 am
ReplyBest website for learning R thanks Joachim.
Re your Example 8 entitled “Create Variable Names Using for-Loop.”
You start with “I’ll show how to create or change variable names” (note “change” is introduced).
Then you only show how to change names (no creation).
I want to create a new variable inside the for loop.
Seems I have to create something to receive the data before creating the loop???Thanks
JeffCansu (Statistics Globe)
March 20, 2023 12:18 pm
ReplyHello Jeff,
Creating the new column names are done in the same way as changing them. So you should simply use the code in the example. See below:
colnames(iris_new2 )<-NULL
head(iris_new2)
# 1 5.1 3.5 1.4 0.2 setosa
# 2 4.9 3.0 1.4 0.2 setosa
# 3 4.7 3.2 1.3 0.2 setosa
# 4 4.6 3.1 1.5 0.2 setosa
# 5 5.0 3.6 1.4 0.2 setosa
# 6 5.4 3.9 1.7 0.4 setosafor(i in 1:ncol(iris_new2)) { # Head of for-loop
colnames(iris_new2)[i] <- paste0("new_", i) # Code block
}
head(iris_new2)
# new_1 new_2 new_3 new_4 new_5
# 1 5.1 3.5 1.4 0.2 setosa
# 2 4.9 3.0 1.4 0.2 setosa
# 3 4.7 3.2 1.3 0.2 setosa
# 4 4.6 3.1 1.5 0.2 setosa
# 5 5.0 3.6 1.4 0.2 setosa
# 6 5.4 3.9 1.7 0.4 setosaRegards,
Cansu
Leave a Reply
I’m Joachim Schork. On this website, I provide statistics tutorials as well as code in Python and R programming.
Statistics Globe Newsletter
Related Tutorials
for-Loop Only Returns Last Value in R (2 Examples)