purrrpurrr packageOctober 2025
In this presentation, we will:
purrr R packagepurrr in the wildIn simple terms, functional programming is a style of programming where you build your code by combining small, self-contained functions instead of writing long, step-by-step procedures.
Basically, this means we break our code into small, reusable functions that can be combined to perform complex tasks.
This approach has several advantages:
|> or %>%).Though R supports different programming styles, it is very good at functional programming.
R, at its heart, is a functional programming (FP) language. This means that it provides many tools for the creation and manipulation of functions. In particular, R has what’s known as first class functions. You can do anything with functions that you can do with vectors: you can assign them to variables, store them in lists, pass them as arguments to other functions, create them inside functions, and even return them as the result of a function.
— Hadley Wickham, Advanced R
In fact, you’re already using functional programming in R even if you don’t realize it.
R excels at vector operations, which are a form of functional programming:
The tidyverse packages are built on functional programming principles:
purrr packageThe purrr package is a powerful tool in R that helps us apply functional programming principles to our data analysis tasks.
purrr is part of the tidyverse, so you can install it with:
or install it on its own.
purrr workhorse: map()map() takes a vector and a function, calls the function once for each element of the vector, and returns the results in a list.
The following two statements are equivalent:
map()map() has two arguments: .x (the input) and .f (the function).
A simple example to illustrate how map() works:
map()The function can be specified in several ways:
The output of map() is always a list. Lists are a very flexible class, but sometimes we want a more specific type of output.
Luckily, there are several map() variants:
| Function | Output class |
|---|---|
map() |
list |
map_lgl() |
logical vector |
map_int() |
integer vector |
map_dbl() |
double vector |
map_chr() |
character vector |
Note: There used to be a map_df() function that returned a data frame, but it has been superseded in favor of using list_rbind() with map().
map_dbl()In our previous example, it would make more sense to return the results as a numeric vector.
purrr with more than one inputOften, we want to apply a function over multiple inputs. purrr has you covered with map2() and pmap().
map(.x, .f) works with one input vector, .xmap2(.x, .y, .f) works with two input vectors, .x and .ypmap(.l, .f) works with more than two input vectors (.l is a list of vectors)map2()map2()Examples from recent projects:
apply() functions in base R? Can’t I just use that?Yes, you can! In some cases, a base R function can do the same thing as a given purrr function.
| Input | Output | purrr |
Base R |
|---|---|---|---|
| 1 vector | list | map() |
lapply() |
| 2 vectors | list | map2() |
mapply() |
| >2 vectors | list | pmap() |
mapply() |
| 1 vector | vector of specific type | map_lgl() (logical), map_int() (integer), map_dbl() (double), map_chr() (character) |
vapply() |
apply() functions in base R? Can’t I just use that?However, purrr offers a more consistent and user-friendly interface, along with additional features that make it easier to work with complex data structures.
purrr functions have a consistent naming scheme, making them easier to learn and remember.map() functions in purrr return outputs of consistent types, reducing unexpected errors.map() functions are the data, so they seamlessly integrate with the pipe and generally integrate smoothly with other tidyverse packages.map() functions have a .progress argument to track the progress of longer jobs.map() functions can be run in parallel using in_parallel() to easily spread computation across multiple cores on your computer, or multiple machines over the network. Formerly, this was only possible with the future_map() functions in the furrr package.safely() and possibly()