Last time, we learned about,
Last time, we learned about,
Today, we will cover,
for()
loopswhile()
loopsIf someone doesn't know better, they might find the means of variables in the swiss
data by typing in a line of code for each column:
mean1 <- mean(swiss$Fertility)mean2 <- mean(swiss$Agriculture)mean3 <- mean(swissExamination)mean4 <- mean(swiss$Fertility)mean5 <- mean(swiss$Catholic)mean5 <- mean(swiss$Infant.Mortality)c(mean1, mean2 mean3, mean4, mean5, man6)
Can you spot the problems?
If someone doesn't know better, they might find the means of variables in the swiss
data by typing in a line of code for each column:
mean1 <- mean(swiss$Fertility)mean2 <- mean(swiss$Agriculture)mean3 <- mean(swissExamination)mean4 <- mean(swiss$Fertility)mean5 <- mean(swiss$Catholic)mean5 <- mean(swiss$Infant.Mortality)c(mean1, mean2 mean3, mean4, mean5, man6)
Can you spot the problems?
How upset would they be if the swiss
data had 200 columns instead of 6?
You will learn a better way to calculate column means today using loops!
means <- rep(NA, ncol(swiss))for(i in 1:ncol(swiss)){ means[i] <- mean(swiss[,i])}data.frame(Variable=names(swiss),Mean=means)
## Variable Mean## 1 Fertility 70.1## 2 Agriculture 50.7## 3 Examination 16.5## 4 Education 11.0## 5 Catholic 41.1## 6 Infant.Mortality 19.9
Don't worry about the details yet!
The DRY idea: Computers are much better at doing the same thing over and over again than we are.
The DRY idea: Computers are much better at doing the same thing over and over again than we are.
The DRY idea: Computers are much better at doing the same thing over and over again than we are.
Writing code to repeat tasks for us reduces the most common human coding mistakes.
It also substantially reduces the time and effort involved in processing large volumes of data.
The DRY idea: Computers are much better at doing the same thing over and over again than we are.
Writing code to repeat tasks for us reduces the most common human coding mistakes.
It also substantially reduces the time and effort involved in processing large volumes of data.
Lastly, compact code is more readable and easier to troubleshoot.
for()
Loopsfor()
Loopfor()
loops are the most general kind of loop, found in pretty much every programming language.
"For each of these values -- in order -- do this"
for()
Loopfor()
loops are the most general kind of loop, found in pretty much every programming language.
"For each of these values -- in order -- do this"
Given a set of values...
i
) equal to the first valuei
)We are looping through values and repeating some actions.
for()
Loop: DiagramGiven a set of values...
for()
Loop: Examplefor(i in 1:5) { # inside for, output won't show up without print() print(i^2) }
## [1] 1## [1] 4## [1] 9## [1] 16## [1] 25
Note this runs 5 separate print commands, which is why each line starts with [1]
.
for(i in 1:3) { print(i^2) }
## [1] 1## [1] 4## [1] 9
i <- 1print(i^2) i <- 2print(i^2)i <- 3print(i^2)
## [1] 1## [1] 4## [1] 9
We call what happens in the loop for a particular value one iteration.
Iterating over indices 1:n
is very common. n
might be the length of a vector, the number of rows or columns in a matrix or data frame, or the length of a list.
We call what happens in the loop for a particular value one iteration.
Iterating over indices 1:n
is very common. n
might be the length of a vector, the number of rows or columns in a matrix or data frame, or the length of a list.
Common notation: i
is the object that holds the current value inside the loop.
j
and k
used for the inner loops.We call what happens in the loop for a particular value one iteration.
Iterating over indices 1:n
is very common. n
might be the length of a vector, the number of rows or columns in a matrix or data frame, or the length of a list.
Common notation: i
is the object that holds the current value inside the loop.
j
and k
used for the inner loops.i
(and j
,k
, etc) are just normal objects. You can use any other names you want.row
and/or col
!What we iterate over doesn't have to be numbers 1:n
or numbers at all! You can also iterate over a character vector in R:
for(i in letters[1:3]) { print(i)}
## [1] "a"## [1] "b"## [1] "c"
i # in R, this will exist outside of the loop!
## [1] "c"
Usually in a for()
loop, you aren't just printing output, but want to store results from calculations in each iteration somewhere.
Usually in a for()
loop, you aren't just printing output, but want to store results from calculations in each iteration somewhere.
To do that, figure out what you want to store, and pre-allocate an object of the right size as a placeholder (typically with missing values as placeholders).
Usually in a for()
loop, you aren't just printing output, but want to store results from calculations in each iteration somewhere.
To do that, figure out what you want to store, and pre-allocate an object of the right size as a placeholder (typically with missing values as placeholders).
Examples of what to pre-allocate based on what you store:
rep(NA, num_iter_iters)
Usually in a for()
loop, you aren't just printing output, but want to store results from calculations in each iteration somewhere.
To do that, figure out what you want to store, and pre-allocate an object of the right size as a placeholder (typically with missing values as placeholders).
Examples of what to pre-allocate based on what you store:
Single numeric value per iteration:
rep(NA, num_iter_iters)
Numeric vector per iteration:
matrix(NA, nrow = num_of_iters, ncol = length_of_vector)
iters <- 10 # Set number of interationsoutput <- rep(NA,iters) # Pre-allocate numeric vector output
## [1] NA NA NA NA NA NA NA NA NA NA
for(i in 1:iters) { # Run code below iters times output[i] <- (i-1)^2 + (i-2)^2}output # Display output
## [1] 1 1 5 13 25 41 61 85 113 145
Steps:
rownums <- 3colnums <- 6output <- matrix(NA,nrow=rownums,ncol=colnums)for(i in 1:rownums){ for(j in 1:colnums){ output[i,j] <- i + j }}output
## [,1] [,2] [,3] [,4] [,5] [,6]## [1,] 2 3 4 5 6 7## [2,] 3 4 5 6 7 8## [3,] 4 5 6 7 8 9
To test a logical statement and then conditionally execute a set of actions, use if()
and else
. The structure is:
if(CONDITION){ SOME CALCULATION} else{ A DIFFERENT CALCULATION}
Warning! else
needs to be on same line as the closing brace }
of previous if()
.
if(8 < 10){ print("Less than 10!")}else{ print("Not less than 10!")}
## [1] "Less than 10!"
We can nest together multiple if/elses! if we wish:
i <- 13if(i <= 10) { print("i is less than or equal to 10!")} else if(i <= 14) { print("i is greater than 10, less than or equal to 14")} else { print("i is greater than or equal to 15")}
## [1] "i is greater than 10, less than or equal to 14"
Suppose we want to take the numbers between 1 and 5, and divide the evens by 2 and multiply the odds by 2. We could do that using a loop with if/else statements!
for(i in 1:5){ if(i %% 2 == 0){ #check for even numbers print(i / 2) }else{ print(i * 2) }}
## [1] 2## [1] 1## [1] 6## [1] 2## [1] 10
Aside from the previous toy example, if()
statements are useful when you have to handle special cases.
if()
statements can be used to make a loop ignore or fix problematic cases.
They are also useful for producing error messages, by generating a message if an input value is not what is expected.
while()
Loopswhile()
A lesser-used looping structure is the while()
loop.
Rather than iterating over a predefined vector, the loop keeps going until some condition is no longer true.
while()
A lesser-used looping structure is the while()
loop.
Rather than iterating over a predefined vector, the loop keeps going until some condition is no longer true.
Here is the structure:
while(COND IS MET){ RUN CODE}
If you're not careful, the while loop will run forever!!
while()
loop example:x <- 0 while(x < 3){ x <- x + 1 print(x)}
## [1] 1## [1] 2## [1] 3
What happened in each iteration?
x <- 0 while(x < 3){ x <- x + 1 print(x)}
## [1] 1## [1] 2## [1] 3
x <- 0x <- x+1print(x)x <- x+1print(x)x <- x+1print(x)
## [1] 1## [1] 2## [1] 3
Let's see how many times we need to flip a coin to get 4 heads:
num_heads <- 0num_flips <- 0while(num_heads < 4) { # simulating a coin flip coin_flip <- rbinom(n = 1, size = 1, prob = 0.5) # keep track of heads if (coin_flip == 1) { num_heads <- num_heads + 1 } # update number of coin flips num_flips <- num_flips + 1 }num_flips # follows negative binomial distribution
## [1] 10
for()
loops: while()
loops: Let's take a 10 minute break, then return for some activities!
for
loop to calculate the maximum value of each variable in the swiss
data. What are the maximum values of each variable?for
loop to calculate the maximum value for each variable in the swiss
data (outer loop), and then divide that maximum by 1, 2, and 4 (inner loop). Print the output after each step.ncol(swiss)
columns and 3 rows. How will you "pre-allocate" space for the results?Question 1:
for(i in 1:ncol(swiss)) { curr_max <- max(swiss[,i]) print(curr_max)}
## [1] 92.5## [1] 89.7## [1] 37## [1] 53## [1] 100## [1] 26.6
Question 2:
for(i in 1:ncol(swiss)) { curr_max <- max(swiss[,i]) for(j in c(1,2,4)){ print(curr_max/j) }}
## [1] 92.5## [1] 46.2## [1] 23.1## [1] 89.7## [1] 44.9## [1] 22.4## [1] 37## [1] 18.5## [1] 9.25## [1] 53## [1] 26.5## [1] 13.2## [1] 100## [1] 50## [1] 25## [1] 26.6## [1] 13.3## [1] 6.65
Question 3:
results <- matrix(NA, ncol=ncol(swiss),nrow=3)for(i in 1:ncol(swiss)) { curr_max <- max(swiss[,i]) for(j in 1:3){ curr_divisor <- c(1,2,4)[j] results[j,i] <- curr_max/curr_divisor }}results
## [,1] [,2] [,3] [,4] [,5] [,6]## [1,] 92.5 89.7 37.00 53.0 100 26.60## [2,] 46.2 44.9 18.50 26.5 50 13.30## [3,] 23.1 22.4 9.25 13.2 25 6.65
1. Consider the vector vec <- c(1,2,NA,3,NA)
. Write a for
loop that includes an if
/else
function so that for each value x
in vec
, we print "Missing!" if x
is NA, and x^3
otherwise.
2. What will happen if I run the following loop:
x <- 1while(x < 10){ print(x + 1)}
3. Write a while()
loop that starts with x <- 1
and doubles x each iteration, while x < 100
. Print x
after each iteration.
1.
for(x in c(1,2,NA,3,NA)){ if(is.na(x)){ print("Missing!") } else{ print(x^3) }}
## [1] 1## [1] 8## [1] "Missing!"## [1] 27## [1] "Missing!"
2. What will happen if I run the following loop:
x <- 1while(x < 10){ print(x + 1)}
1
, since we are not updating x
!!3. Write a while()
loop that starts with x <- 1
and doubles x each iteration, while x < 100
. Print x
after each iteration.
x <- 1while(x <100){ x <- x * 2 print(x)}
## [1] 2## [1] 4## [1] 8## [1] 16## [1] 32## [1] 64## [1] 128
Why does x
reach 128?!
HW 6 will be posted on the website shortly! Remember that it is a continuation of HW 5!
Last time, we learned about,
Keyboard shortcuts
↑, ←, Pg Up, k | Go to previous slide |
↓, →, Pg Dn, Space, j | Go to next slide |
Home | Go to first slide |
End | Go to last slide |
Number + Return | Go to specific slide |
b / m / f | Toggle blackout / mirrored / fullscreen mode |
c | Clone slideshow |
p | Toggle presenter mode |
t | Restart the presentation timer |
?, h | Toggle this help |
Esc | Back to slideshow |