Repeating Things 2 (reference card)

Basic for loop

  • For loops perform the same action for each item in a list of items
  • Use print() to display values inside the loop
vector_of_things <- c(1.6, 3, 8, 10)
for (thing in vector_of_things){
  transformed_things <- 2.65 * thing ^ 0.9
  print(transformed_things)
}

Looping with an index & storing results

  • Use ‘length()’ function to create an index for each position and then use the position
  • Lets us store output
vector_of_things <- c(1.6, 3, 8, 10)
results <- vector(mode = "numeric", length = length(vector_of_things_1))
for (i in 1:length(vector_of_things)){
  calculated_value <- 2.65 * vector_of_things[i] ^ 0.9
  results[i] <- calculated_value
}

Looping over multiple values

  • Use the index to look up the required value in each vector
vector_of_things_1 <- c(1.6, 3, 8)
vector_of_things_2 <- c(2.65, 1.28, 3.29)
vector_of_things_3 <- c(0.9, 1.1, 1.2)
results <- vector(mode = "numeric", length = length(vector_of_things_1))
for (i in seq_along(vector_of_things_1)){
  calculated_value <- vector_of_things_2[i] * vector_of_things_1[i] ^ vector_of_things_3[i]
  results[i] <- calculated_value
}

Sequence along loops

  • Use seq_along() instead of 1:length() to avoid weird edge cases with empty vectors
for (i in seq_along(vector_of_things)){
  calculated_value <- 2.65 * vector_of_things[i] ^ 0.9
  results[i] <- calculated_value
}
results

Looping with functions

  • Can call functions in loops to run them repeatedly
non_vectorized_function <- function(input_1, input_2, input_3){
  if (input_1 < 5) {
    output_value <- input_2 * input_1 ^ input_3
  } else {
    output_value <- NA
  }
  return(output_value)
}

vector_of_things_1 <- c(1.6, 3, 8, 10)
results <- vector(mode = "numeric", length = length(vector_of_things_1))
for (i in seq_along(vector_of_things_1)){
  calculated_value <- non_vectorized_function(vector_of_things_1[i], vector_of_things_2[i], vector_of_things_3[i])
  results[i] <- calculated_value
}

Looping over files

  • List files in directory that match a naming pattern
data_files <- list.files(pattern = "patter-to-match-filenames")
  • Then loop over those file names reading the file and working with it
results <- vector(mode = "integer", length = length(data_files))
for (i in seq_along(data_files)){
  filename <- data_files[i]
  data <- read_csv(filename)
  count <- nrow(data)
  results[i] <- count
}

Store loop results in a data frame

  • Create empty data frame using tibble() and one argument for each column
results <- tibble(
  file_name = vector(mode = "character", length = length(data_files)),
  count = vector(mode = "integer", length = length(data_files)),
  min_value = vector(mode = "numeric", length = length(data_files))
)
  • Store results in the column in the data frame, e.g., results$count[i]
for (i in seq_along(data_files)){
  filename <- data_files[i]
  data <- read_csv(filename)
  count <- nrow(data)
  min_value <- min(data$column_name)
  results$file_name[i] <- filename
  results$count[i] <- count
  results$min_value[i] <- min_value
}