rollfun: Apply Rolling Function

Description Usage Arguments Details Examples

Description

Apply a rolling function to the margins of data.

Usage

1
2
rollfun(x, w, FUN, ..., by = 1, front = TRUE, list.out = FALSE,
  simplify = FALSE, partial = FALSE)

Arguments

x

vector, matrix or data.frame; data representing a series
of observations

w

single integer; width of the rolling window

FUN

closure; function to be applied

...

optional arguments passed to FUN

by

single integer; step length of the window

front

logical; when w is odd, should the result be biased to the front?

list.out

logical; should output be returned as list?

simplify

logical; should output be simplified?
Typically from list to data.frame or matrix

partial

logical; should partial results at the ends be calculated?

Details

rollfun() is functionally very similar to zoo::rollapply(), but slightly simplified.
w and by can only be single positive integers, meaning that window width and step length
are always constant. When applied to a multi column object all columns will be passed to
FUN, unless otherwise stated in FUN. Output can be forced to list format with
list.out=TRUE. If output from FUN is anything other than scalar, list.out must be set to
TRUE. simplify=TRUE will apply do.call(rbind, .) to the output, meaning that the
'simplest' it can get is a one column matrix. simplify is ignored if list.out=TRUE.
Output will always be the same length (or nrow) as input. Ends are padded with NA, except
when partial=TRUE. When by > 1 both ends and empty intervals will be padded with NA.

Examples

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# rolling median absolute deviation (mad)
rollfun(rnorm(15), 7, mad, constant=1)


# rolling mad vs rolling sd
set.seed(1)
r <- rnorm(500, 0, sin(1:500/50) + 2) * rexp(500)
f <- function(x) c(mad(x), sd(x) * -1)

plot(r, pch=16, cex=0.5)
for (i in 1:25) {
	rf <- rollfun(r, i*5, f, list.out=TRUE, simplify=TRUE, partial=TRUE)
    matlines(rf, col=c("#FF000066", "#0000FF66"), lty=1)
}


# plot rolling 5-number statistic
data(xyz)
summ.df <- rollfun(xyz, 33, summary, list.out=TRUE, simplify=TRUE)

plot(xyz, pch=16, cex=0.4)
matlines(summ.df[, -4], type="l", lty=1, lwd=2, 
  col=rainbow(5, start=0.5, alpha=0.8))


# rolling percentiles
set.seed(1)
s1 <- c(seq(2.5, 0.5, , 1000), rep(0.5, 500))
s2 <- sin(1:1500/1500*2*pi) + 1.5
xr <- rbeta(length(s1), s1, s2)
 
probs <- seq(0, 1, , 101)
r <- rollfun(xr, 150, list.out=TRUE, partial=TRUE, simplify=TRUE,
  function(z) quantile(z, probs, names=FALSE))

cf <- colorRampPalette(c("#00FF44", "cyan", "#0044FF"), space="Lab", bias=0.8)
matplot(r, type="l", lty=1, lwd=0.4+(0.0005*(-50:50)^2),
  col=cf(101), xaxs="i", yaxs="i")
box()

# rolling piecewise linear regression
lm.fun <- function(x) {
	lm(x ~ seq_along(x))
}

data(xyz2)
models <- rollfun(xyz2, 40, by=1, lm.fun, list.out=TRUE, simplify=FALSE)
notna <- which(!is.na(models))

plot(xyz2, pch=16, col="red")

for (i in notna) {
	vals <- fitted(models[[i]])
	lines(seq_along(vals) + i - min(notna), vals, lwd=1.5,
	  col="#00000040")
}


# rolling stepped piecewise polynomial regression
plm.fun <- function(x, p=4) {
	lm(x ~ poly(seq_along(x), p))
}

s <- 80
models <- rollfun(xyz2, s, by=63, plm.fun, list.out=TRUE, simplify=FALSE)
notna <- which(!is.na(models))

plot(xyz2, pch=16, col="red")

for (i in notna) {
	vals <- fitted(models[[i]])
	lines(seq_along(vals) + i - min(notna), vals, lwd=4,
	  col="#000000A0")
}


# rolling linear regression, plotting slope, intercept and p-value
set.seed(1)
s1 <- sin((1:300/100)*pi*2) + 
  rnorm(300, 0, seq(0.1, 1, length.out=300))

s2 <- sin((1:300/50)*pi*2) + 
  rnorm(300) +
  tanh(s1/3)

s2 <- ema(s2, 20)
  
dtf <- data.frame(s2, s1)

lm.fun <- function(x) {
    vn <- colnames(x)
    form <- as.formula(paste(vn[1], "~", vn[2]))
	mod <- as.data.frame(summary(lm(form, data=x))$coefficients)
	num <- c(mod$Estimate, mod$"Pr(>|t|)")
	names(num) <- rownames(mod)
	num
}

models <- rollfun(dtf, 25, lm.fun, list.out=TRUE, simplify=TRUE)
plot(as.ts(models), nc=2, mar.multi=c(0, 4.1, 0, 1))


### demonstrating output formats
# when FUN output is scalar
rollfun(1:9, 3, mean)

# setting list.out=TRUE makes it a list of scalars
rollfun(1:9, 3, mean, list.out=TRUE)

# setting list.out=TRUE and simplify=TRUE returns a single column matrix
rollfun(1:9, 3, mean, list.out=TRUE, simplify=TRUE)

# when FUN output is a vector
# the following will fail as output is not scalar
rollfun(1:9, 3, function(x) c(x[1], x[2]))

# setting list.out=TRUE makes it work
rollfun(1:9, 3, function(x) c(x[1], x[2]), list.out=TRUE)

# setting list.out=TRUE and simplify=TRUE returns a matrix
rollfun(1:9, 3, function(x) c(x[1], x[2]), list.out=TRUE, simplify=TRUE)

# when FUN output is a list
# setting list.out=TRUE makes it work
rollfun(1:9, 3, function(x) list(x[1], x[2]), list.out=TRUE)

# setting list.out=TRUE and simplify=TRUE returns a matrix
rollfun(1:9, 3, function(x) list(x[1], x[2]), list.out=TRUE, simplify=TRUE)

AkselA/R-rollfun documentation built on May 31, 2019, 8:41 a.m.