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
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…