knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
library(Rdlazer)
Here is what we have covered so far:
\newline
If you find yourself confused by this part, consider reading the Environments vignette.
the enclosing environment
the calling environment
the execution environment
function
functionfunction
are the formal arguments of the function being definedfunction
is the body of the function being definedreturn
return
immediately ends the function call, all subsequent expressions are ignoredf <- function(x, y = 9L) { cat('x and y will be added', '\n') z <- x + y cat('the sum will be pasted to a string constant', '\n') ans <- paste('text', z) cat('the result wil be returned', '\n') return(ans) cat('I am being ignored', '\n') ans <- paste(ans, 'redoubled') return(ans) } # the defined function is assigned as the variable f # f has two formal arguments, x and y; y has a default value of 9L # during the call a variable called ans is created and returned # returning ends the call f(3)
return
is optionalf2 <- function(x, y = 9) { cat('x and y will be added', '\n') z <- x + y cat('the sum will be pasted to a string constant', '\n') cat('the pasted text will be implicitly returned', '\n') paste('text', z) } f2(3)
\newline
function(x, y) {z <- x + y; as.character(z)}(3, 5) function(x, y) {x + y}(3, 5) (function(x, y) x + y)(3, 5)
\newline
SIDENOTE
fs <- function(x, y = NULL) { y toupper(x) } # y is not specified, defaults to NULL fs('text') # y is specified as a call to stop, which signals an error and terminates the call fs('text', stop('not so fast!', call. = FALSE)) fns <- function(x, y = NULL) { toupper(x) } fns('text') fns('text', stop('not so fast!')) # the error is ignored as no expression in the body refers to it
END OF SIDENOTE
v1 <- 1:5 # this is a vectorized operation: v2 <- v1 < 3 # these are not any(v2) isTRUE(v2)
\newline
lapply
lapply
takes a vector and a functionv <- c('one', 'two') vn <- setNames(v, c('item1', 'item2')) lapply(v, identity) lapply(vn, identity) lapply(as.list(vn), identity)
\newline
identity
doesn't quite display the power of lapply
# get the vectors in list form l <- as.list(iris[1:4]) # run lapply lapply(l, mean)
l2 <- vector(mode = 'list', length = length(l)) for (i in seq_along(l)) { l2[[i]] <- mean(l[[i]]) } names(l2) <- names(l) l2
lapply
can be faster as the looping is done in C (the language that runs "under the hood" of R)lapply
makes for neater codeff <- function(x, text = 'text') { y <- mean(x) y <- round(y, 2) ans <- paste0(text, ': ', y) return(ans) } lapply(l, ff)
\newline
X
argument in a lapply
call, the one we iterate over, is the first formal argument of the function we applylapply
call; they will be the same for every iterationlapply(l, ff, text = 'the mean value is') lapply(list(iris, mtcars), head, n = 2)
\newline
lapply
accepts anonymous functions# get the mean of each list element lapply(l, mean) # alternative with anonymous function lapply(l, function(x) mean(x)) # get the first element of each list item lapply(l, function(x) x[1]) # get the first and third element of each list item lapply(l, function(x) c(x[1], x[3])) # get the first and last elements lapply(l, function(x) c(x[1], x[length(x)]))
\newline
seps <- c(',', ', ', ' - ', '_') l[[1]] lapply(seps, function(x) paste(l[[1]], collapse = x))
lapply
Family Memberslapply
sapply
does basically the same thing with two major differences:lapply(v, identity) sapply(v, identity)
sapply
will behave consistently but not always predictably# simplifying can involve coercion ll <- list(one = '1', two = 1) sapply(ll, identity) # it can also be impossible lll <- list(one = 1:2, two = 1) sapply(lll, identity)
vapply
is sapply
with safety measures:FUN
, e.g. "character of length 1"vapply(ll, identity, character(1)) vapply(v, identity, character(1))
vapply
is recommended over sapply
in programming (calling it within a function)mapply
is a "multivariate" version of sapply
mapply(paste, l, collapse = seps)
...
MoreArgs
as a listsapply(X, FUN)
(vector first) vs mapply(FUN, ..., MoreArgs)
(function first)replicate
is a little differentreplicate(5, 1:4)
# create 5 random samples (10 items each) of a normal distribution replicate(5, rnorm(10)) # compute mean of a random sample (10k items) replicate(100, { s <- rnorm(1e+4) mean(s) }) # capture the means and compute their mean means <- replicate(100, { s <- rnorm(1e+4) sm <- mean(s) }) head(means) mean(means)
# random pertumation sample(6) # another random permutation sample(6) # assigned random permutation ("captured") (p <- sample(6)) # the permutation remains "captured" p # p stores the value returned by the call to sample, not the function call itself
\newline
Check out the Vectorize
function too.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.