I am trying to use the terra::roll()
function to compute a rolling geometric mean. I created another function to calculate the geometric mean, but that function has arguments I would like to pass through. See reprex below, how do I make a function that roll()
can call and pass additional args to it?
Thanks
# geomean function with arguments
geomean <- function(v, floor = 0.1, na.rm = TRUE){
exp(sum(log(v[v > floor]), na.rm=na.rm) / length(v))
}
# outer function for rolling geomean
rollgm <- function(x, N = 30, type = 'to', ...) {
terra::roll(as.vector(x), N, geomean, type = type, ...) # ... should be passed to geomean()
}
# example
d <- c(runif(10), NA, NA, runif(10))
rollgm(d, N=5, type = 'to', floor = 0.5) # error unused argument floor
# how to pass through the floor argument ?
Apparently, roll
does not pass the arguments in ...
to the function specified in the fun
argument (see terra::roll source code). However, you could define geomean
inside the outer function using the passed arguments as default values:
# outer function for rolling geomean
rollgm <- function(x, N = 30, type = 'to', gm.floor = 0.1, gm.na.rm = TRUE, ...) {
# define inside outer function with specified arguments
# note that 'floor = floor' would cause an error (recursive default argument reference),
# hence the 'gm.' prefix
geomean <- function(v, floor = gm.floor, na.rm = gm.na.rm){
exp(sum(log(v[v > floor]), na.rm = na.rm) / length(v))
}
# help(terra::roll): ... additional arguments for writing files as in writeRaster
terra::roll(x = as.vector(x), n = N, fun = geomean, type = type, ...)
}
# example
d <- c(runif(10), NA, NA, runif(10))
rollgm(d, N = 5, type = 'to', gm.floor = 0.5) # no error
rollgm(d, N = 5, type = 'to', gm.floor = 0.5, gm.na.rm = FALSE) # no error