# The apply Family and purrr — R Programming

Source: https://www.geekswithgeeks.com/en/r-programming/p-apply

> 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.

```r
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 199
```

## Use 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.

**Quiz:** Which purrr function returns a numeric (double) vector, failing if any result is not a single number?

- [ ] map
- [ ] keep
- [x] map_dbl
- [ ] reduce

*Answer:* map_dbl. map_dbl guarantees a double vector output.
