library(learnr) tutorial_options(exercise.reveal_solution = FALSE) gradethis::gradethis_setup() knitr::opts_chunk$set( collapse = TRUE, comment = ">", error = TRUE ) set.seed(123)
Loops allow you to repeat the same thing again and again. If you are doing something more than two or three times, you should instead use a loop to avoid having to copy and paste the same code over and over again. Since duplicating code risks not only mistyping or not copying correctly, but also creating confusion by filling your R scripts with nearly identical chunks of code. There are fundamentally two kinds of loop:
for
loopsfor
loops allow us to repeat something for a fixed number of times (e.g.
once per element of a vector, once per row of a data frame, etc.).
A for
loop always has the same style:
for (one in many) { # Do something # ... exciting code maybe using the variable # one (but it doesn't have to) ... }
It looks a bit like a function, but what it does is set the variable one
to
each of the values in many
one at a time, and then does something. Here are two
very simple examples to get an idea of what it might do:
greetings <- c("Hello", "Goodbye") for (word in greetings) { print(word) }
Try changing the greetings
variable. You'll see that the loop runs once for each
word in the greetings
vector. We can use this to do something a fixed number of
times without necessarily caring about the entries:
# Make a sequence of 7 numbers from 1 to 7 times <- seq(from = 1, to = 7) # This is the same as 1:7 or seq(1, 7) # Print "I'm in a loop" repeatedly for (iteration in times) { print("I'm in a loop") }
Change the length of the times
vector. You'll see that it prints out the
text once for each element in times
even though it never looks to see what
iteration
is (it doesn't care).
Now look at this code:
# A function to add one to a number add_one <- function(number) number + 1 # Initialise the value current.value <- 0 current.value <- add_one(current.value) current.value <- add_one(current.value) current.value <- add_one(current.value) current.value <- add_one(current.value) current.value <- add_one(current.value) # Output the updated current.value at the end to see what happened current.value
grade_result(pass_if(~identical(.result, 10)))
It just runs our add_one()
function from earlier five times to update the
variable current.value
to 5. Change the code so it does this ten times to
produce 10.
Now look at this next piece of code:
# A function to add one to a number add_one <- function(number) { number + 1 } # Initialise the value current.value <- 0 # This now is a loop! for (loop in 1:10) { current.value <- add_one(current.value) } # Output the updated current.value at the end to see what happened current.value
grade_result(pass_if(~identical(.result, 100)))
It does the same thing - it calls add_one()
ten times, but it's much shorter,
which generally makes it easier to see what's going on. Now change the code
to call add_one()
100 times. Hopefully you can see that this is really
starting to help now!
And you can probably imagine that if it was any more complicated that just copying and pasting one line it would make it much easier to see that it was doing exactly the same thing each time too.
Finally, add in the single line print(paste("Loop number", loop))
into the
loop at the end (between lines 11 and 12) and run it. You'll now be able see
each step of the loop running. We'll use techniques like this later to check
that the loop is doing the right thing.
Note also that unlike functions, variables changed in for
loops do change
what happens outside the loop, so current.value
is 100
at the end, and not
still 0
.
There is a section in R4DS (within a more general chapter on
Iteration) that covers for
loops. For loops
are also covered by R Coder here.
while
loopswhile
loops allow us to repeat something while a condition is still TRUE
.
They are particularly useful when you don't know in advance exactly how many
times something will be done, but can be used in any situation. Unlike for
loops though, you need to update everything manually each time around:
x <- 1 test <- x < 3 while (test) { # Do something print(x) # Update x and update test x <- x + 1 test <- x < 3 }
test
is checked at the beginning of each iteration, and as long as test
continues to be TRUE
, the code block inside the curly brackets { ... }
is
run. The test after the while
statement acts exactly like a if
statement
that we looked at in A-1, except that it is run repeatedly until it is FALSE
,
so refer back to there to remind you how if
and tests work.
Be careful though... if you don't update test
inside the curly brackets, your
loop will continue forever! However, if (when!) test
is finally FALSE
, the
loop will end and R will continue on to the next line of code after the loop.
There is a
section in R4DS (within a more general chapter on Iteration)
that covers while
loops. While loops are also covered by R Coder
here.
Now try the following exercise, combining an if
statement with a for
loop to
print greetings (not duck
):
greetings <- c("Hello", "Goodbye", "duck") for (word ___) { if (___) { print(___) } }
greetings <- c("Hello", "Goodbye", "duck") for (word in greetings) { if (word != "duck") { print(word) } }
grade_this_code()
Solve the following problem -- a countdown from 10 to 1.
x <- 10 while (___) { # Do something print(x) if (x == 1) print("Blast off!") # Update test x <- ___ }
x <- 10 while (x > 0) { # Do something print(x) if (x == 1) print("Blast off!") # Update test x <- x - 1 }
grade_this_code()
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.