Skip to content
Lesson 7 of 9

Step 1 of 5 · Reading · ~1 min

Learn

Functions

for loops in R have a reputation for being slow. The apply family is the idiomatic way to repeat operations:

sapply(x, f) - apply f to each element of x, simplify to a vector:

sapply(1:5, function(n) n * 2)    # 2 4 6 8 10
sapply(c("hi", "hello"), nchar)   # 2 5

lapply(x, f) - same but always returns a list (no simplification):

lapply(1:3, function(n) rep(n, n))
# list(1, c(2,2), c(3,3,3))

sapply simplifies only when it can. Give it the same function and it also hands back a list, because results of length 1, 2 and 3 do not fit in one vector. That "sometimes a vector, sometimes a list" behaviour is exactly why vapply(x, f, FUN.VALUE) exists - you state the return template and get an error instead of a surprise. Safer for production code.

Map(f, x, y) - multi-arg version. Map("+", 1:3, 10:12) gives list(11, 13, 15).

These feel functional because they are. R draws heavily from Lisp's roots.

Two results that surprise people

A bare expression at the top level of an Rscript is printed for you - in print layout, not as clean output. And sapply over a character vector names its result after the input, so those names come along as a header row:

words <- c("hello", "world", "foo")
sapply(words, nchar)
# hello world   foo
#     5     5     3

Assigning the result silences the auto-print, and USE.NAMES = FALSE (or unname) drops the names:

lens <- sapply(words, nchar, USE.NAMES = FALSE)
cat(lens, sep=" ")   # 5 5 3
Up nextLists and Named ListsData Frames

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…