Apply a Function to Components of a List or Vector

DESCRIPTION:

Apply a function to components of a list or other object, return results as a list, vector, or matrix.

USAGE:

lapply(X, FUN, ...)
sapply(X, FUN, ..., simplify=T, USE.NAMES = T, USE.FUN.VALUE.NAMES = F)

REQUIRED ARGUMENTS:

X
any S-PLUS object (including bigdata); usually a list. Missing values ( NAs) are allowed if FUN accepts them.
FUN
function to apply to components of X. Or a character string giving the name of the function; this is easier for functions with unusual names, e.g., "/".

OPTIONAL ARGUMENTS:

...
other arguments to FUN, if any.
simplify
logical flag: if TRUE, the result is simplified, if possible.
USE.NAMES
logical flag: if TRUE, and if X is a character vector, use X as names for the result unless names already exist. In the unlikely case where the names already exist, then X is combined with the existing name.
USE.FUN.VALUE.NAMES
logical flag: For internal use only; not intended to be set manually.

VALUE:

for lapply, a list like X (same length and names) where each component of the list is replaced by the result of executing FUN on that component. The components of X are passed as the first argument to FUN that is not matched by one of the ... arguments.

VALUE:

for sapply, object whose first value(s) is (are) the result of FUN applied to the first component of X, and so on. If all the results are the same length and simplify is TRUE , sapply returns a matrix with one column for each component; if all the results are scalars, a vector is returned. Otherwise, or if simplify=FALSE, a list like lapply.

NOTE:

apply applies a function to specified subsets of an array. tapply operates on data classified by categorical variables.

DETAILS:

lapply calls a function for each element of a list and always returns a list. sapply calls lapply, then attempts to simplify to a vector or matrix.

These functions are also useful for looping (as a faster alternative to for) by letting X be a vector such as 1:n . See examples below.

Avoiding Scoping Problems with lapply() or sapply():

S scoping rules require that you pass in as an argument to an *apply() function any object defined outside of your local call. For more information about S scoping rules, see the chapter "Data Management," in the Programmer's Guide, or see Chapter 3, "The S Language: Advanced Aspects" in S-Programming, Venables & Ripley, 2000.

ISSUES:

When FUN is a generic function, lapply and sapply will sometimes not find the proper function when you call lapply(X,FUN) . It will work if you use lapply(X,function(x)FUN(x)). This applies to any function that takes another function as an argument, not just to lapply and sapply .

SEE ALSO:

, .

EXAMPLES:

# Create list containing vectors of varying lengths:
x <- lapply(15:20, runif)

#apply mean function with 'trim' argument to each element of list x
lapply(x, mean, trim=.1)
sapply(x, mean, trim=.1)

sapply(x, sort) # sort the components: will be a matrix if
# all components of x are the same length and a list otherwise

# apply mean to the stack.loss data with various values of trim
# Here X is the second argument to the function!
lapply(list(0, .05, .1, .25, .5), mean, x=stack.loss)

# inverse; again X is the second argument.
lapply(x, "/", e1 = 1.0)

# generate a list with elements 1, 1:2, 1:3, ...
lapply(1:5, seq)

# generate a list with elements 1, c(2, 2), c(3, 3, 3), ...
lapply(1:5, function(x) rep(x,x))

# Example using floor() as the generic function 
# (bigdata library section must be loaded)
sapply(as.bdFrame(fuel.frame)[,-5], function(x)floor(x))

# Looping using for(), and equivalent loop using sapply
result <- rep(NA, 100); for(i in 1:100) result[i] <- sum(1:i)
result2 <- sapply(1:100, function(i) sum(1:i))

# Get classes of all datasets on database "data"
temp <- objects(where="data")
names(temp) <- temp   # names will be used by sapply
sapply(temp, function(i) class(get(i)))

# Find classes of columns of a data frame
sapply(Puromycin, class)

# To operate on two lists let X be a vector of indices
list1 <- lapply(1:6, runif)  # artificial data for this example
list2 <- lapply(1:6, runif)
lapply(1:6, function(i, x, y) x[[i]] + y[[i]],
       x = list1, y = list2)

# If you call lapply() from another function, and get a message
# about an object not found, it is probably because the object is
# local to the function and is not visible globally.
x <- list(a = runif(300), b = rnorm(20))
trimmedMeans <- function(x, myTrim){
  f <- function(x) mean(x, trim = myTrim)
  lapply(x, f)
}
#           trimmedMeans(x, .2)
# The previous line would fail, because myTrim is local to trimmedMeans.
#
# The recommended solution is to use ...
# The inner function (f) must take an additional argument, and the
# outer function (trimmedMeans) should pass that argument
# when calling lapply:
trimmedMeans <- function(x, myTrim){
  f <- function(x, myTrim) mean(x, trim = myTrim)
  lapply(x, f, myTrim = myTrim)
}
trimmedMeans(x, .2)