rguides

Map

Map() is a base R function that applies a function to multiple arguments in parallel. It is equivalent to mapply() with simplification disabled, meaning it always returns a list regardless of the result shape.

Relationship to mapply

Map() is a thin wrapper around mapply:

Map(f, x, y)
# identical to
mapply(f, x, y, SIMPLIFY = FALSE)

The difference is that Map() never attempts to simplify the result. mapply() tries to collapse the list into a matrix or vector when all results are scalar, Map() skips that step. This makes Map() the safer choice in pipelines: you always get a list back, and there is no risk of dimension collapse when one element returns a different-length vector than expected.

Basic usage

# Apply a function to two vectors element-wise
Map(\(x, y) x + y, 1:3, 10:12)
# [[1]]
# [1] 11
# [[2]]
# [1] 13
# [[3]]
# [1] 15

# Compare to mapply (which simplifies)
mapply(\(x, y) x + y, 1:3, 10:12)
# [1] 11 13 15

Parameter details

ParameterTypeDefaultDescription
FUNfunctionRequiredFunction to apply
...vectors/listsRequiredArguments to iterate over
MoreArgslistNULLAdditional fixed arguments to pass to FUN
USE.nameslogicalTRUEIf TRUE and any argument has names, the result inherits those names
SIMPLIFYlogicalFALSEAlways FALSE for Map (enforced)

Working with names

# Names are preserved when USE.names = TRUE (default)
Map(\(name, val) paste0(name, ": ", val),
    c(a = "apple", b = "banana"),
    1:2)
# $a
# [1] "apple: 1"
# $b
# [1] "banana: 2"

When USE.names = TRUE (the default), the result list inherits names from the first named argument that has them. This is convenient for keeping the output self-documenting — each element is labelled with the input key that produced it. Setting USE.names = FALSE suppresses name inheritance, which can be useful when names are meaningless or when constructing output programmatically.

Passing extra arguments

Use MoreArgs to pass additional fixed arguments:

f <- function(x, y, z) x + y * z

Map(f, 1:3, 10:12, MoreArgs = list(z = 2))
# [[1]]
# [1] 21
# [[2]]
# [1] 25
# [[3]]
# [1] 29

The MoreArgs parameter separates fixed arguments from iterated ones — anything in MoreArgs is passed as-is to every invocation of FUN, while positional ... arguments are iterated element by element. This is cleaner than wrapping FUN in an anonymous function that hard-codes the fixed values, and it avoids a performance penalty from repeated function definitions.

Multiple list inputs

# Apply function across multiple lists
x <- list(a = 1, b = 2)
y <- list(a = 10, b = 20)
z <- list(a = 100, b = 200)

Map(\(a, b, c) a + b + c, x, y, z)
# $a
# [1] 111
# $b
# [1] 222

Map() in base R

Map() is the base R equivalent of mapply() with SIMPLIFY = FALSE. It applies a function to corresponding elements of multiple lists or vectors, always returning a list. Unlike mapply(), it never simplifies the output, this makes Map() more predictable in pipelines where you need guaranteed list output.

Map(f, x, y) is equivalent to mapply(f, x, y, SIMPLIFY = FALSE). For two-input operations over vectors, Map() is a clean alternative to a for loop: Map(paste, names, values) produces a list of concatenated strings. When the output should be a vector rather than a list, wrap with unlist() or use mapply() directly.

Map() does not recycle arguments, all inputs must have the same length, and it raises an error if they differ. This strict length requirement is a feature when working with logically paired data: it prevents silent misalignment that recycling might hide.

The tidyverse alternative is purrr::map2() for two inputs or purrr::pmap() for any number of inputs. These provide type-safe variants (map2_dbl(), pmap_chr()) and better error messages. Map() is appropriate when you want no external dependencies and the default list output is sufficient.

When to use map vs mapply

Use Map() when you want predictable list output. Use mapply() when you want the result simplified to a vector or matrix, but be aware that simplification can fail in unexpected ways if the return types vary.

# Safe: always list, no surprises
result <- Map(function(x) if (x > 1) "big" else "small", 1:3)
str(result)
# List of 3

# mapply simplifies when possible
result <- mapply(function(x) if (x > 1) "big" else "small", 1:3)
str(result)
#  chr [1:3] "small" "big" "big"

See also