for (thing in list_of_things) {
do_something(thing)
}Repeating Things 2 (reference card)
Basic for loop
- for loops perform the same action for each item in a list of things
- ‘print()’ to display values inside the loop
list_of_things = c(1.6, 3, 8, 10)
for (thing in list_of_things){
transformed_things <- 2.65 * thing ^ 0.9
print(transformed_things)
}- Code takes the first value from list_of_things (in this vector ‘1.6’), assigns it to ‘thing’, does the calculation and prints it
- Then it takes the second value from list_of_things (in this vector ‘3’), assigns it to ‘thing’, does the calculation and prints it
- and so on through the numbers in the vector vector (‘list_of_things’)
Looping with an index & storing results
volumes = c(1.6, 3, 8)
for (i in 1:length(volumes)){
mass <- 2.65 * volumes[i] ^ 0.9
print(mass)
}- use ‘length()’ function
- lets us do more complicated things!
Sequence along loops
for (i in seq_along(volumes)){
mass <- 2.65 * volumes[i] ^ 0.9
masses[i] <- mass
}
masses- this avoids looping over vector twice if empty vector
Looping over multiple values
as <- c(2.65, 1.28, 3.29)
bs <- c(0.9, 1.1, 1.2)
volumes = c(1.6, 3, 8)
masses <- vector(mode="numeric", length=length(volumes))
for (i in seq_along(volumes)){
mass <- as[i] * volumes[i] ^ bs[i]
masses[i] <- mass
}- ‘as’, ‘bs’, ‘volumes’ are vectors
- each vector is implemented into the loop taking the first value of each vector, then the second value of each vector and then the third value of each vector, and so on.
Looping with functions
example function:
est_mass_max <- function(volume, a, b){
if (volume < 5) {
mass <- a * volume ^ b
} else {
mass <- NA
}
return(mass)
}- note: can’t pass the vector to the function and get back a vector of results because of the if statements
Loop over the values: - First create an empty vector to store the results - Then loop by index, calling the function for each value of volumes
volumes = c(1.6, 3, 8)
masses <- vector(mode="numeric", length=length(volumes))
for (i in seq_along(volumes)){
mass <- est_mass_max(volumes[i], as[i], bs[i])
masses[i] <- mass
}- note: results are stored in the vector masses
Looping over files
- list files in directory with files that start with ‘locations-’
data_files = list.files(pattern = "locations-")- create empty vector to store counts
results <- vector(mode = "integer", length = length(data_files))- loop over list count the number of observations in each file
for (i in seq_along(data_files)){
filename <- data_files[i]
data <- read_csv(filename)
count <- nrow(data)
results[i] <- count
}- optional: Add ‘show_col_types = FALSE’ to read_csv to avoid noisy output
Store loop results in a data frame
- Create empty data frame
- Use ‘data.frame()’ function and one argument(what type of data will be going in) for each column
results <- data.frame(
file_name = vector(mode = "character", length = length(data_files)),
count = vector(mode = "integer", length = length(data_files)),
min_lat = vector(mode = "numeric", length = length(data_files))
)- Instead of storing count in ‘results[i]’. First specify the count column using the ‘\(' : 'results\)count[i]’
- Store the filename, which is ‘data_files[i]’
for (i in seq_along(data_files)){
filename <- data_files[i]
data <- read_csv(filename)
count <- nrow(data)
min_lat = min(data$lat)
results$file_name[i] <- filename
results$count[i] <- count
results$min_lat[i] <- min_lat
}Nested Loops
for (i in 1:10) {
for (j in 1:5) {
print(paste("i = " , i, "; j = ", j))
}
}- nested loops work by putting one loop inside another one
Looping over data frames
- loop over columns
data <- data.frame(a = as, b = bs, volume = volumes)
for (i in data) {
print(i)
}- loop over rows
for (i in 1:nrow(data)) {
print(data[i, ])
}- loop over specific column
masses <- vector(mode="numeric", length=length(volumes))
for (i in 1:nrow(data)) {
mass <- est_mass_max(data[i, "volume"], data[i, "a"], data[i, "b"])
masses[i] <- mass
}