100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

The apply Family of Functions

How R's apply family — lapply, sapply, apply, vapply, and mapply — replaces explicit loops with predictable, functional-style iteration.

Control Flow & FunctionsIntermediate9 min readJul 10, 2026
Analogies

Introduction to the apply Family

The apply family — sapply(), lapply(), apply(), mapply(), and vapply() — provides a functional alternative to explicit for loops by applying a function to every element of a vector, list, or margin of a matrix, and returning the results collected into a single object. Choosing the right member of the family mostly comes down to what shape of input you have (a vector/list versus a matrix/data frame) and what shape of output you want (a list, a simplified vector, or a guaranteed type).

🏏

Cricket analogy: A fitness coach running the same beep test protocol on every player in the squad and compiling all 15 results into one summary table mirrors sapply() applying one function across every element and collecting the outputs.

sapply() and lapply()

lapply(X, FUN) always returns a list, with one element per input element, preserving names if X is named, which makes it the predictable, type-safe workhorse of the family; sapply(X, FUN) calls lapply() internally and then attempts to simplify the result into a vector or matrix when every element has the same length, but silently falls back to returning a plain list when the results aren't uniform, which is convenient interactively but risky inside production code because the output type can vary depending on the data. lapply(mylist, function(x) x^2) on a list of numeric vectors returns a list where each element has been squared.

🏏

Cricket analogy: lapply() is like a scorer meticulously recording each batsman's individual scorecard in its own labeled folder without trying to merge them, while sapply() tries to staple all the scorecards into one neat summary sheet when the format allows, but keeps them as separate folders if the innings lengths differ.

r
nums <- list(a = 1:3, b = 4:6, c = 7:9)

lapply(nums, sum)
# $a
# [1] 6
# $b
# [1] 15
# $c
# [1] 24        (a list)

sapply(nums, sum)
#  a  b  c
#  6 15 24        (simplified to a named numeric vector)

apply() for Matrices and Data Frames

apply(X, MARGIN, FUN) is specifically for matrices and data frames, applying FUN across rows when MARGIN = 1 or across columns when MARGIN = 2 (and both simultaneously with MARGIN = c(1, 2)), which makes it the natural tool for computing something like a row-wise total or a column-wise mean across a whole table. Because apply() coerces its input to a matrix first, applying it to a data frame with mixed column types (numeric and character together) will silently coerce everything to character, which is a common source of subtle bugs, so apply() is best reserved for genuinely homogeneous, all-numeric matrices.

🏏

Cricket analogy: apply(scorecard, 1, sum) totals each batsman's runs across all innings row by row, while apply(scorecard, 2, mean) computes the average score for each innings column across all batsmen — row versus column aggregation.

r
m <- matrix(1:6, nrow = 2)
apply(m, 1, sum)   # row sums:    9 12 15 -> combined per row
apply(m, 2, mean)  # column means, one value per column

mapply() and vapply() for Type Safety

vapply(X, FUN, FUN.VALUE) is the type-safe cousin of sapply(): it requires you to specify FUN.VALUE, a template describing the exact type and length FUN should return for each element (like numeric(1) for a single number), and it throws an informative error immediately if any call produces something that doesn't match that template, which makes it much safer to use inside functions or packages where an unexpected input could otherwise cause sapply() to return a differently-shaped result. mapply(FUN, X, Y) is the multivariate version, iterating over two or more vectors in parallel and passing corresponding elements of each to FUN simultaneously, similar to calling FUN(X[1], Y[1]), FUN(X[2], Y[2]), and so on.

🏏

Cricket analogy: vapply(scores, calc_average, numeric(1)) enforces that every single player's calculation must return exactly one number, immediately flagging a data-entry error if any player's record produces something else, unlike sapply() which might silently return an inconsistent structure.

mapply(function(x, y) x + y, X = c(1,2,3), Y = c(10,20,30)) applies the function pairwise across both vectors simultaneously, equivalent to c(1+10, 2+20, 3+30); Map() is a thin wrapper around mapply() with SIMPLIFY = FALSE that always returns a list, which is often clearer inside code that will be passed straight into another lapply()-style call.

sapply()'s automatic simplification is convenient in interactive exploration but dangerous inside reusable functions: if the input happens to be empty or produces results of inconsistent length, sapply() can silently return a list instead of the numeric vector your downstream code expects, causing an error far from its actual cause — use vapply() with an explicit FUN.VALUE whenever the function's output feeds into further processing.

  • lapply() always returns a list with one element per input, making it predictable and type-safe.
  • sapply() calls lapply() internally and tries to simplify the result, but silently falls back to a list when outputs aren't uniform.
  • apply(X, MARGIN, FUN) works on matrices/data frames: MARGIN = 1 for rows, MARGIN = 2 for columns.
  • apply() coerces its input to a matrix first, so mixed-type data frames get silently coerced to character.
  • vapply() requires a FUN.VALUE template and errors immediately if a result doesn't match, unlike sapply().
  • mapply() (and its wrapper Map()) iterates over two or more vectors in parallel, applying FUN to corresponding elements.
  • Prefer vapply() over sapply() inside functions or packages where predictable output type matters.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#RProgrammingStudyNotes#TheApplyFamilyOfFunctions#Apply#Family#Functions#Sapply#StudyNotes#SkillVeris#ExamPrep