runmin & runmax | R Documentation |
Moving (aka running, rolling) Window Minimum and Maximum calculated over a vector
runmin(x, k, alg=c("C", "R"),
endrule=c("min", "NA", "trim", "keep", "constant", "func"),
align = c("center", "left", "right"))
runmax(x, k, alg=c("C", "R"),
endrule=c("max", "NA", "trim", "keep", "constant", "func"),
align = c("center", "left", "right"))
x |
numeric vector of length n or matrix with n rows. If |
k |
width of moving window; must be an integer between one and n |
endrule |
character string indicating how the values at the beginning
and the end, of the array, should be treated. Only first and last
Similar to |
alg |
an option allowing to choose different algorithms or
implementations. Default is to use of code written in C (option |
align |
specifies whether result should be centered (default),
left-aligned or right-aligned. If |
Apart from the end values, the result of y = runFUN(x, k) is the same as
“for(j=(1+k2):(n-k2)) y[j]=FUN(x[(j-k2):(j+k2)], na.rm = TRUE)
”, where FUN
stands for min or max functions. Both functions can handle non-finite
numbers like NaN's and Inf's the same way as min(x, na.rm = TRUE)
).
The main incentive to write this set of functions was relative slowness of
majority of moving window functions available in R and its packages. With the
exception of runmed
, a running window median function, all
functions listed in "see also" section are slower than very inefficient
“apply(embed(x,k),1,FUN)
” approach. Relative
speeds runmin
and runmax
functions is O(n) in best and average
case and O(n*k) in worst case.
Both functions work with infinite numbers (NA
,NaN
,Inf
,
-Inf
). Also default endrule
is hardwired in C for speed.
Returns a numeric vector or matrix of the same size as x
. Only in case of
endrule="trim"
the output vectors will be shorter and output matrices
will have fewer rows.
Jarek Tuszynski (SAIC) jaroslaw.w.tuszynski@saic.com
Links related to:
Other moving window functions from this package: runmean
,
runquantile
, runmad
and runsd
R functions: runmed
, min
, max
Similar functions in other packages: rollmax
from zoo library
generic running window functions: apply
(embed(x,k), 1, FUN)
(fastest), running
from gtools
package (extremely slow for this purpose), subsums
from
magic library can perform running window operations on data with any
dimensions.
# show plot using runmin, runmax and runmed
k=25; n=200;
x = rnorm(n,sd=30) + abs(seq(n)-n/4)
col = c("black", "red", "green", "blue", "magenta", "cyan")
plot(x, col=col[1], main = "Moving Window Analysis Functions")
lines(runmin(x,k), col=col[2])
lines(runmean(x,k), col=col[3])
lines(runmax(x,k), col=col[4])
legend(0,.9*n, c("data", "runmin", "runmean", "runmax"), col=col, lty=1 )
# basic tests against standard R approach
a = runmin(x,k, endrule="trim") # test only the inner part
b = apply(embed(x,k), 1, min) # Standard R running min
stopifnot(all(a==b));
a = runmax(x,k, endrule="trim") # test only the inner part
b = apply(embed(x,k), 1, max) # Standard R running min
stopifnot(all(a==b));
# test against loop approach
k=25;
data(iris)
x = iris[,1]
n = length(x)
x[seq(1,n,11)] = NaN; # add NANs
k2 = k
k1 = k-k2-1
a1 = runmin(x, k)
a2 = runmax(x, k)
b1 = array(0,n)
b2 = array(0,n)
for(j in 1:n) {
lo = max(1, j-k1)
hi = min(n, j+k2)
b1[j] = min(x[lo:hi], na.rm = TRUE)
b2[j] = max(x[lo:hi], na.rm = TRUE)
}
# this test works fine at the R prompt but fails during package check - need to investigate
## Not run:
stopifnot(all(a1==b1, na.rm=TRUE));
stopifnot(all(a2==b2, na.rm=TRUE));
## End(Not run)
# Test if moving windows forward and backward gives the same results
# Two data sets also corespond to best and worst-case scenatio data-sets
k=51; n=200;
a = runmin(n:1, k)
b = runmin(1:n, k)
stopifnot(all(a[n:1]==b, na.rm=TRUE));
a = runmax(n:1, k)
b = runmax(1:n, k)
stopifnot(all(a[n:1]==b, na.rm=TRUE));
# test vector vs. matrix inputs, especially for the edge handling
nRow=200; k=25; nCol=10
x = rnorm(nRow,sd=30) + abs(seq(nRow)-n/4)
x[seq(1,nRow,10)] = NaN; # add NANs
X = matrix(rep(x, nCol ), nRow, nCol) # replicate x in columns of X
a = runmax(x, k)
b = runmax(X, k)
stopifnot(all(a==b[,1], na.rm=TRUE)); # vector vs. 2D array
stopifnot(all(b[,1]==b[,nCol], na.rm=TRUE)); # compare rows within 2D array
a = runmin(x, k)
b = runmin(X, k)
stopifnot(all(a==b[,1], na.rm=TRUE)); # vector vs. 2D array
stopifnot(all(b[,1]==b[,nCol], na.rm=TRUE)); # compare rows within 2D array
# Compare C and R algorithms to each other for extreme window sizes
numeric.test = function (x, k) {
a = runmin( x, k, alg="C")
b = runmin( x, k, alg="R")
c =-runmax(-x, k, alg="C")
d =-runmax(-x, k, alg="R")
stopifnot(all(a==b, na.rm=TRUE));
#stopifnot(all(c==d, na.rm=TRUE));
#stopifnot(all(a==c, na.rm=TRUE));
stopifnot(all(b==d, na.rm=TRUE));
}
n=200; # n is an even number
x = rnorm(n,sd=30) + abs(seq(n)-n/4) # random data
for(i in 1:5) numeric.test(x, i) # test for small window size
for(i in 1:5) numeric.test(x, n-i+1) # test for large window size
n=201; # n is an odd number
x = rnorm(n,sd=30) + abs(seq(n)-n/4) # random data
for(i in 1:5) numeric.test(x, i) # test for small window size
for(i in 1:5) numeric.test(x, n-i+1) # test for large window size
n=200; # n is an even number
x = rnorm(n,sd=30) + abs(seq(n)-n/4) # random data
x[seq(1,200,10)] = NaN; # with some NaNs
for(i in 1:5) numeric.test(x, i) # test for small window size
for(i in 1:5) numeric.test(x, n-i+1) # test for large window size
n=201; # n is an odd number
x = rnorm(n,sd=30) + abs(seq(n)-n/4) # random data
x[seq(1,200,2)] = NaN; # with some NaNs
for(i in 1:5) numeric.test(x, i) # test for small window size
for(i in 1:5) numeric.test(x, n-i+1) # test for large window size
# speed comparison
## Not run:
n = 1e7; k=991;
x1 = runif(n); # random data - average case scenario
x2 = 1:n; # best-case scenario data for runmax
x3 = n:1; # worst-case scenario data for runmax
system.time( runmax( x1,k,alg="C")) # C alg on average data O(n)
system.time( runmax( x2,k,alg="C")) # C alg on best-case data O(n)
system.time( runmax( x3,k,alg="C")) # C alg on worst-case data O(n*k)
system.time(-runmin(-x1,k,alg="C")) # use runmin to do runmax work
system.time( runmax( x1,k,alg="R")) # R version of the function
x=runif(1e5); k=1e2; # reduce vector and window sizes
system.time(runmax(x,k,alg="R")) # R version of the function
system.time(apply(embed(x,k), 1, max)) # standard R approach
## End(Not run)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.