purrr::reduce()
reduce(.x, .f, ..., .init) same type as .init or .x · Updated March 13, 2026 · Tidyverse The reduce() and accumulate() functions from the purrr package implement a fold (or cumulative reduction) over the elements of a vector or list. reduce() applies a binary function successively to combine all elements into a single value, while accumulate() returns a vector of the same length containing all intermediate results. These functions are fundamental for expressing iterative computations—such as sums, products, string concatenation, or any operation that combines elements pairwise—in a concise, functional style that avoids explicit loops.
Syntax
reduce(.x, .f, ..., .init)
accumulate(.x, .f, ..., .init)
Typed variants: reduce_right(), accumulate_right() (start from the right), and reduce2() / accumulate2() for two input vectors.
Parameters
reduce() / accumulate()
| Parameter | Type | Default | Description |
|---|---|---|---|
.x | list, vector, or data frame | Required | Input elements to combine |
.f | binary function (two arguments) | Required | Function that combines two values; first argument is the accumulated result, second is the next element |
... | any | Optional | Additional arguments passed to .f |
.init | any | NULL | Initial value. If supplied, the first call to .f receives .init and the first element of .x. If omitted, the first call uses the first two elements of .x. |
reduce_right() / accumulate_right()
Same parameters but iteration proceeds from the last element to the first.
reduce2() / accumulate2()
| 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 minus one when .init is NULL, else same length as .x) |
.f | ternary function (three arguments) | Required | Function that combines accumulated result, current element of .x, and current element of .y |
... | any | Optional | Additional arguments passed to .f |
.init | any | NULL | Initial value (see above) |
The .f argument can be a function, formula, or character string, following the same rules as map().
Examples
Basic reduce(): sum of a vector
library(purrr)
nums <- c(1, 2, 3, 4, 5)
reduce(nums, `+`)
# [1] 15
# Equivalent to 1 + 2 + 3 + 4 + 5
Using .init
# Concatenate strings with a separator
words <- c("Hello", "world", "from", "R")
reduce(words, paste, sep = " ")
# [1] "Hello world from R"
# With an initial value
reduce(words, paste, sep = " ", .init = "Message:")
# [1] "Message: Hello world from R"
accumulate(): track intermediate sums
accumulate(nums, `+`)
# [1] 1 3 6 10 15
# First element is nums[1], second is nums[1] + nums[2], etc.
reduce2(): pairwise multiplication with a second vector
x <- c(1, 2, 3)
y <- c(10, 20, 30)
reduce2(x, y, function(acc, a, b) acc + a * b, .init = 0)
# [1] 140
# Steps: 0 + 1*10 = 10, 10 + 2*20 = 50, 50 + 3*30 = 140
accumulate_right(): build a nested list from the right
accumulate_right(1:3, ~ list(.y, .x))
# [[1]]
# [[1]][[1]]
# [1] 1
#
# [[1]][[2]]
# [[1]][[2]][[1]]
# [1] 2
#
# [[1]][[2]][[2]]
# [1] 3
#
#
#
# [[2]]
# [[2]][[1]]
# [1] 2
#
# [[2]][[2]]
# [1] 3
#
#
# [[3]]
# [1] 3
Common Patterns
Flattening a list of lists
nested <- list(list(1, 2), list(3, 4), list(5, 6))
reduce(nested, c)
# [[1]]
# [1] 1
#
# [[2]]
# [1] 2
#
# [[3]]
# [1] 3
#
# [[4]]
# [1] 4
#
# [[5]]
# [1] 5
#
# [[6]]
# [1] 6
Computing a cumulative product with a custom function
accumulate(1:5, ~ .x * .y)
# [1] 1 2 6 24 120
Implementing a simple queue with reduce
# Simulate processing a queue of tasks
tasks <- list(
function(x) x + 1,
function(x) x * 2,
function(x) x ^ 3
)
reduce(tasks, function(state, f) f(state), .init = 5)
# [1] 1728
# Steps: 5 + 1 = 6, 6 * 2 = 12, 12 ^ 3 = 1728
Using reduce with data frames to join multiple tables
library(dplyr)
dfs <- list(
data.frame(id = 1:2, a = c("x", "y")),
data.frame(id = 2:3, b = c("p", "q")),
data.frame(id = 3:4, c = c("r", "s"))
)
reduce(dfs, full_join, by = "id")
# id a b c
# 1 1 x <NA> <NA>
# 2 2 y p <NA>
# 3 3 <NA> q r
# 4 4 <NA> <NA> s
Performance Considerations
reduce()is implemented in C++ and is fast for vectors of moderate size.- For very long vectors, consider whether the operation can be vectorised directly (e.g.,
sum()instead ofreduce(+)). accumulate()allocates a result vector of the same length as the input; if you only need the final result, usereduce().reduce_right()andaccumulate_right()are slightly slower because they reverse the input before processing.