0

You can pass function (in this example mean) to rollapply at least in two different ways (note round brackets in 2nd example) as it is shown here:

> sub.as.avg.1 <- rollapply(sub.as, width = 1,  by = 1,  FUN = mean,   align = "left")
> sub.as.avg.1 <- rollapply(sub.as, width = 1,  by = 1,  FUN = (mean), align = "left")

Now I want to pass function from variable. This one is working:

> fun
[1] "mean"
> r2 <- rollapply(sub.as, width = 1, by = 1, FUN = (fun), align = "left")
>

But this one is not:

> fun
[1] "(mean)"
> r2 <- rollapply(sub.as, width = 1, by = 1, FUN = fun, align = "left")
Error in get(as.character(FUN), mode = "function", envir = envir) : 
  object '(mean)' of mode 'function' was not found

How to make this work? What does round brackets mean for rollapply? Are they rollapply specific or it is something general to R?

EDIT: Based on @DavidGo answer I've tried following:

library(zoo)

sub.as <- c(1, 0.75, 0.9, 0.475, 0.925, 0.975, 1, 1, 0.525, 1, 0.2, 0.2, 
 0.2, 0.2, 0.15, 0.15, 0.15, 0.15, 0.15, 0.45, 0.875, 0.175, 0.15, 
 0.15, 0.15, 0.1, 0.1, 0.1, 0.1, 0.35, 1)

my.func <- function(x, fun){
  result.vec <- rollapply(x, width = 1, by = 1, FUN = fun, align = "left")
  result.vec
}

r1 <- my.func(sub.as, mean)
r2 <- my.func(sub.as, (mean))

But it seems like if I were using (mean) in both cases:

> sub.as - r1
 [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
> sub.as - r2
 [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
> identical(sub.as, r1)
[1] TRUE
> identical(sub.as, r2)
[1] TRUE
Community
  • 1
  • 1
Wakan Tanka
  • 7,542
  • 16
  • 69
  • 122
  • Use the `eval(parse` if you really want to go that route. i.e. `rollapply(sub.as, width = 1, by = 1, FUN = eval(parse(text=fun)), align = "left")` – akrun Mar 07 '16 at 12:36
  • Please check the updated comment. BTW, it should work for both `fun`s – akrun Mar 07 '16 at 12:37
  • Why are you passing `"(mean)"`? If you want ensure that the optimization of calling `rollmean` is not used and pass the function dymically, just pass the default S3 method `"mean.default"`. `rollapply` checks if `mean` has been passed by using `deparse(substitute(FUN))`. Like this: `fun <- function(FUN) { deparse(substitute(FUN)) }; fun((mean))`. You can reproduce the error you are seeing like this: `match.fun("(mean)")`. – Roland Mar 07 '16 at 13:01
  • If you pass a character string or an expression that evaluates to a character string to the `FUN=` argument of `rollapply` then that character string must contain the name of the function you want to use. There is no function named `(mean)`. Note that if you do pass a character string to `rollapply` it will not call `rollmean` so there is no point in parenthesizing a character string. – G. Grothendieck Mar 07 '16 at 13:18

1 Answers1

0

it seems that you initialize fun like this: fun = "(mean)" while in the example you provided it is a closure. If you want to stick to the example you could enter:

library(zoo)
sub.as <- c(1, 0.75, 0.9, 0.475, 0.925, 0.975, 1, 1, 0.525, 1, 0.2, 0.2, 
 0.2, 0.2, 0.15, 0.15, 0.15, 0.15, 0.15, 0.45, 0.875, 0.175, 0.15, 
 0.15, 0.15, 0.1, 0.1, 0.1, 0.1, 0.35, 1)
fun <- (mean) # or fun <- mean
r2 <- rollapply(sub.as, width = 1, by = 1, FUN = fun, align = "left")

otherwise you could also convert your character like this:

fun = eval(parse("(mean)")), align = "left")

no matter how you do it, rollapply expects FUN as a closure

EDIT @Roland is right, as the function (mean) does not exists as a proper function, and the function rollmean that is called internally can't be passed to rollapply directly, you need to implement a workaround. I did it like that, which might not be the most elegant way but it should work as you'd expect:

library(zoo)
my.func <- function(x, fun){
  if (deparse(substitute(fun)) == "mean") {
    result.vec <- rollapply(x, width = 1, by = 1, FUN = mean, align = "left")
  }
  else{
    result.vec <- rollapply(x, width = 1, by = 1, FUN = fun, align = "left") 
  }
  return(result.vec)
}
sub.as <- c(1, 0.75, 0.9, 0.475, 0.925, 0.975, 1, 1, 0.525, 1, 0.2, 0.2, 
            0.2, 0.2, 0.15, 0.15, 0.15, 0.15, 0.15, 0.45, 0.875, 0.175, 0.15, 
            0.15, 0.15, 0.1, 0.1, 0.1, 0.1, 0.35, 1)
r1 <- my.func(sub.as, mean)
r2 <- my.func(sub.as, (mean))
r3 <- rollapply(sub.as, width = 1, by = 1, FUN = mean, align = "left")
r4 <- rollapply(sub.as, width = 1, by = 1, FUN = (mean), align = "left")
print(identical(r1,r2))
print(identical(r1,r3))
print(identical(r4,r2))
David Go
  • 810
  • 1
  • 7
  • 13