Lesson 9 / 25
The apply Family and purrr
Apply functions over vectors and lists with sapply, lapply and purrr's map functions.
Functional iteration
Instead of writing loops, R code often applies a function to each element of a vector or list. Base R provides lapply() (always returns a list), sapply() (simplifies to a vector or matrix when possible, which can be unpredictable), vapply() (like sapply but with a declared output type, safer in functions), apply() for rows or columns of a matrix, mapply() for several inputs, and tapply() for grouped summaries. The tidyverse's purrr offers a more consistent family: map() returns a list, and typed variants map_dbl(), map_chr(), map_lgl() and map_int() return vectors of a guaranteed type (or fail loudly); map2() and pmap() iterate over several inputs; keep(), discard() and reduce() filter and combine; and safely() and possibly() wrap functions so one failure does not stop the whole iteration. These tools are ideal for reading many files, fitting a model per group or calling an API for each ID.
lapply, vapply and purrr
Typed map functions fail loudly instead of returning surprising shapes.
library(purrr)
files <- c("jan.csv", "feb.csv", "mar.csv")
# read every file into a list of data frames, then combine them
monthly <- lapply(files, readr::read_csv)
all_sales <- dplyr::bind_rows(monthly, .id = "file_index")
words <- c("pen", "notebook", "ink")
vapply(words, nchar, integer(1)) # typed base R: 3 8 3
map_int(words, nchar) # purrr equivalent
prices <- c(49.5, 120, 199)
qty <- c(3, 1, 2)
map2_dbl(prices, qty, \(p, q) p * q) # 148.5 120.0 398.0
parse_amount <- possibly(\(s) as.numeric(gsub(",", "", s)), otherwise = NA_real_)
map_dbl(c("1,200", "350", "oops"), parse_amount) # 1200 350 NA (with a coercion warning)
keep(prices, \(p) p > 100) # 120 199Use typed outputs
sapply may return a list, a vector or a matrix depending on the data, which breaks code later. vapply or map_dbl/map_chr guarantee the output type and fail immediately if an element does not fit.
Quick check: Which purrr function returns a numeric (double) vector, failing if any result is not a single number?
- map
- keep
- map_dbl
- reduce
Answer
map_dbl — map_dbl guarantees a double vector output.