R: Apply a function over a rolling range of a data structure
maprange
R Documentation
Apply a function over a rolling range of a data structure
Description
Either applies a function over a rolling range of a sequence or
multiple sequences bound as a matrix or data.frame.
Arguments
x
Any indexable data structure
window
The length of the sub-sequence to pass to fn
fn
A function applied to a rolling range of x
do.pad
Whether to pad the output to be the same length as the input
by
The gap between two contiguous windows.
Value
In the 1D case, a vector of length(x) - window + 1 (unless padded)
will be returned. Otherwise a matrix with dimension
length(x) - window + 1 by ncol(x) will be returned.
Usage
maprange(x, window, fn, do.pad=FALSE, by=1)
Details
This function is intended to work primarily with time series-like
objects where the same statistic is computed over a rolling window
of the time series. In other packages this operation is referred to as
rollapply (e.g. zoo). This version has two significant differences from
other implementations: 1) it is purely functional, and therefore
easy to reason about; 2) it has consistent semantics with the
family of map functions; 3) it has an extra parameter by to set the
gap between two contiguous windows.
A typical use case for the by parameter is like this: you have
a monthly time series, and need to calculate a metric over a rolling window
of 12 months, but the start point of each window is every quarter end.
Normally you'd have to roll through every months then filter out those
that start at quarter end. Now you can just set by=3 and get your
result in one line.
Comparing the code for zoo:::rollapply.zoo, which is close to 100 lines,
versus the 3 lines separated into 2 function clauses clearly
demonstrates the conciseness inherent in functional programming.
Mathematics is known for being very compact and powerful. When
utilized appropriately, functional programs share this same property.
Author(s)
Brian Lee Yung Rowe
See Also
mapmapblock
Examples
# Compute a 5-period moving average over a vector
maprange(rnorm(20), 5, mean, do.pad=TRUE)
# Same as above, but do it for 4 time series
maprange(matrix(rnorm(80),ncol=4), 5, mean, do.pad=TRUE)