do.call
do.call evaluates a function call constructed with call(). The primary use case is passing arguments stored in a list, programmatically constructing function calls, or dynamically dispatching to functions by name.
Signature
do.call(what, args, quote = FALSE, envir = parent.frame())
Arguments:
what— a function, or a character string naming a function to callargs— a list or pairlist of arguments to pass to the functionquote— ifTRUE,argsis treated as an unevaluated expression (Language object)envir— the environment in which to evaluate the call
Returns: The result of calling what with the provided arguments.
How do.call Relates to call()
call() constructs a call object without evaluating it. do.call() evaluates that call.
# call() builds the unevaluated expression
call("mean", x = 1:10)
# => mean(x = 1:10)
# do.call() evaluates it
do.call("mean", list(x = 1:10))
# => 5.5
call() alone does not run the function — it returns a Language object. do.call() is what actually fires the function.
Basic Usage
Pass arguments as a named list:
do.call("paste", list("a", "b", sep = "-"))
# => "a-b"
Works with any function, including built-ins and user-defined:
my_summary <- function(x, na.rm = TRUE) {
c(mean = mean(x, na.rm = na.rm),
sd = sd(x, na.rm = na.rm))
}
do.call(my_summary, list(1:10, na.rm = TRUE))
# => mean 5.5, sd 3.03
Constructing Calls Dynamically
Building Arguments from a List
When arguments are stored in a list, do.call is cleaner than using do.call(..., envir = ) alternatives:
args <- list(1, 2, 3)
do.call("+", args)
# => 6
Using do.call with User Functions
The args list must be named if your function expects named arguments:
calculate <- function(operation, x, y) {
switch(operation,
add = x + y,
multiply = x * y)
}
do.call(calculate, list(operation = "add", x = 3, y = 4))
# => 7
Combining with match.call
A powerful pattern captures the call in a function and replays it with do.call:
wrapper <- function(f, data, ...) {
call_obj <- match.call()
call_obj[[1]] <- as.name("do.call")
call_obj$f <- as.name(f)
eval(call_obj)
}
# This builds and runs do.call(f, list(data, ...))
do.call vs Direct Calling
The difference is only visible when arguments live in a list:
# Direct call:
result <- mean(c(1, 2, 3))
# Equivalent with do.call:
result <- do.call(mean, list(c(1, 2, 3)))
do.call is necessary when the arguments must be collected or manipulated as data:
args <- split(mtcars$mpg, mtcars$cyl)
do.call(rbind, args)
Here rbind() gets called with all the list elements as separate arguments — something impossible to write directly without do.call.
Common Use Cases
Apply a Function to Split Data
results <- do.call(rbind, lapply(split(mtcars, mtcars$gear), function(df) {
data.frame(gear = df$gear[1], mean_mpg = mean(df$mpg))
}))
Dynamic Function Dispatch
operations <- list(
mean = function(x) base::mean(x),
median = function(x) stats::median(x)
)
op <- "median"
do.call(operations[[op]], list(1:10))
# => 5.5
Building a Call from Components
func_name <- "t.test"
args <- list(x = rnorm(100), y = rnorm(100), var.equal = TRUE)
do.call(func_name, args)
See Also
- /reference/base-functions/apply/ — apply functions over margins
- /reference/base-functions/lapply/ — apply functions to lists
- /reference/base-functions/match/ — match elements to a target