Repeating Things 2 (reference card)

Basic for loop

  • for loops perform the same action for each item in a list of things
for (thing in list_of_things) {
  do_something(thing)
}
  • ‘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
}