purrr::reduce()

reduce(.x, .f, ..., .init)
Returns: same type as .init or .x · Updated March 13, 2026 · Tidyverse
purrr reduce accumulate functional-programming 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()

ParameterTypeDefaultDescription
.xlist, vector, or data frameRequiredInput elements to combine
.fbinary function (two arguments)RequiredFunction that combines two values; first argument is the accumulated result, second is the next element
...anyOptionalAdditional arguments passed to .f
.initanyNULLInitial 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()

ParameterTypeDefaultDescription
.xlist, vector, or data frameRequiredFirst input sequence
.ylist, vector, or data frameRequiredSecond input sequence (must be same length as .x minus one when .init is NULL, else same length as .x)
.fternary function (three arguments)RequiredFunction that combines accumulated result, current element of .x, and current element of .y
...anyOptionalAdditional arguments passed to .f
.initanyNULLInitial 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 of reduce(+)).
  • accumulate() allocates a result vector of the same length as the input; if you only need the final result, use reduce().
  • reduce_right() and accumulate_right() are slightly slower because they reverse the input before processing.

See Also