purrr::map()
map(.x, .f, ...) list · Updated March 13, 2026 · Tidyverse The map() family of functions from the purrr package provides a consistent, type‑safe way to apply a function to each element of a list or vector. Unlike base R’s lapply() and sapply(), purrr’s map functions enforce predictable output types, offer better error messages, and integrate seamlessly with the tidyverse. map() applies a function to a single vector, map2() iterates over two vectors in parallel, and pmap() iterates over an arbitrary number of vectors stored in a list. Together they form the core of purrr’s functional programming toolkit, enabling readable, modular code that avoids explicit loops.
Syntax
map(.x, .f, ...)
map2(.x, .y, .f, ...)
pmap(.l, .f, ...)
The functions also have typed variants that coerce the result to a specific atomic type: map_int(), map_dbl(), map_chr(), map_lgl(), map_dfr(), map_dfc(), etc.
Parameters
map()
| Parameter | Type | Default | Description |
|---|---|---|---|
.x | list, vector, or data frame | Required | The input to iterate over |
.f | function, formula, or atomic vector | Required | The function to apply to each element |
... | any | Optional | Additional arguments passed to .f |
map2()
| Parameter | Type | Default | Description |
|---|---|---|---|
.x | list, vector, or data frame | Required | First input sequence |
.y | list, vector, or data frame | Required | Second input sequence (must be same length as .x) |
.f | function, formula, or atomic vector | Required | Function applied to each pair .x[[i]], .y[[i]] |
... | any | Optional | Additional arguments passed to .f |
pmap()
| Parameter | Type | Default | Description |
|---|---|---|---|
.l | list of lists, vectors, or data frames | Required | A list where each element is a vector of the same length; iteration proceeds over the i‑th elements of each sub‑list |
.f | function, formula, or atomic vector | Required | Function applied to each set of elements across .l |
... | any | Optional | Additional arguments passed to .f |
The .f argument can be:
- A named function (e.g.,
mean) - An anonymous function (e.g.,
function(x) x + 1) - A formula (e.g.,
~ .x + 1), where.x(and.y,.zforpmap) refer to the current element(s) - A character string naming a function (e.g.,
"mean") - An integer, used to extract that element from each input (e.g.,
1extracts the first element)
Examples
Basic map() usage
library(purrr)
# Convert a list of character vectors to their lengths
words <- list("apple", "banana", "cherry")
map(words, nchar)
# [[1]]
# [1] 5
#
# [[2]]
# [1] 6
#
# [[3]]
# [1] 6
# Use a typed variant to get an integer vector directly
map_int(words, nchar)
# [1] 5 6 6
# Apply a custom function with additional arguments
map(words, paste, "-fruit", sep = "")
# [[1]]
# [1] "apple-fruit"
#
# [[2]]
# [1] "banana-fruit"
#
# [[3]]
# [1] "cherry-fruit"
Parallel iteration with map2()
# Multiply corresponding elements of two vectors
x <- c(1, 2, 3)
y <- c(10, 20, 30)
map2(x, y, ~ .x * .y)
# [[1]]
# [1] 10
#
# [[2]]
# [1] 40
#
# [[3]]
# [1] 90
# Use typed variant to return a numeric vector
map2_dbl(x, y, ~ .x * .y)
# [1] 10 40 90
# Combine strings from two lists
first_names <- c("Alice", "Bob", "Charlie")
last_names <- c("Smith", "Jones", "Brown")
map2_chr(first_names, last_names, paste, sep = " ")
# [1] "Alice Smith" "Bob Jones" "Charlie Brown"
Flexible iteration with pmap()
# Create a list of vectors with the same length
args <- list(
a = c(1, 2, 3),
b = c(4, 5, 6),
c = c(7, 8, 9)
)
# Sum across the three vectors element‑wise
pmap(args, sum)
# [[1]]
# [1] 12
#
# [[2]]
# [1] 15
#
# [[3]]
# [1] 18
# Use a data frame as input (each row becomes a set of arguments)
df <- data.frame(
x = 1:3,
y = 4:6,
z = 7:9
)
pmap(df, ~ ..1 + ..2 + ..3) # ..1 refers to the first column, etc.
# [[1]]
# [1] 12
#
# [[2]]
# [1] 15
#
# [[3]]
# [1] 18
# Use a named list with a formula
pmap(args, ~ .a + .b + .c)
# [[1]]
# [1] 12
#
# [[2]]
# [1] 15
#
# [[3]]
# [1] 18
Common Patterns
Transforming nested data
# Extract a column from each data frame in a list
list_of_dfs <- list(
data.frame(id = 1:2, value = c("a", "b")),
data.frame(id = 3:5, value = c("c", "d", "e"))
)
map(list_of_dfs, "value")
# [[1]]
# [1] a b
# Levels: a b
#
# [[2]]
# [1] c d e
# Levels: c d e
Error handling with safely() and possibly()
# Wrap a function that may fail
safe_log <- safely(log)
results <- map(c(1, 2, -1, 4), safe_log)
# Extract successful results
transpose(results)$result
# [[1]]
# [1] 0
#
# [[2]]
# [1] 0.6931472
#
# [[3]]
# NULL
#
# [[4]]
# [1] 1.386294
# Use possibly() to provide a default value
possibly_log <- possibly(log, otherwise = NA)
map_dbl(c(1, 2, -1, 4), possibly_log)
# [1] 0.0000000 0.6931472 NA 1.3862944
Building pipelines with the pipe
library(dplyr)
library(purrr)
# Map over a list, filter results, then combine
list(1:3, 4:6, 7:9) %>%
map(~ .x * 2) %>%
keep(~ mean(.x) > 5) %>%
reduce(c)
# [1] 8 10 12 14 16 18
Working with data frames row‑wise
# Apply a function to each row of a data frame
df <- data.frame(a = 1:3, b = 4:6, c = 7:9)
pmap(df, function(a, b, c) a + b + c)
# [[1]]
# [1] 12
#
# [[2]]
# [1] 15
#
# [[3]]
# [1] 18
# Use pmap with mutate to create a new column
df %>%
mutate(total = pmap_dbl(., ~ ..1 + ..2 + ..3))
# a b c total
# 1 1 4 7 12
# 2 2 5 8 15
# 3 3 6 9 18
Performance Considerations
map()is generally faster thanlapply()for small to medium‑sized data because of its C++ backend.- Typed variants (
map_int,map_dbl, etc.) avoid the overhead of list creation and are recommended when the output type is known. - For very large vectors, consider
future_map()from the furrr package for parallel execution. - When using
pmap()with data frames, be aware that each row is turned into a list; for wide data frames this can incur overhead.