2

I want to do sth like in the figure with a Weibull distribution. enter image description here

But somehow I can't get it to work using stat_function. I get argument missing errors. Adding args=list(..) does not work.

limitRange <- function(fun, min, max) {
  function(x) {
    y <- fun(x)
    y[x < min  |  x > max] <- NA
    return(y)
  }
}      

ggplot(data.frame(x=c(0,3)), aes(x)) +
  stat_function(fun = dweibull, 
                args = list(shape = 2, scale = 1.12), alpha = .8, size = 1.1) + # works
  stat_function(fun = limitRange(dweibull(shape = 2, scale = 1.12), 0.0297, 0.1189),
                args = list(shape = 2, scale = 1.12), #doesn't work
                geom = "area", fill = "blue", alpha = 0.2) 

Any help much appreciated.

B--rian
  • 5,578
  • 10
  • 38
  • 89
  • The problem isn't with `stat_function` but with `limitRange`. Run `lr = limitRange(dweibull(shape = 2, scale = 1.12), 0.0297, 0.1189)` and then run `lr(-3)` --- you get the same error. (Don't have a solution yet...) – Gregor Thomas Feb 27 '19 at 16:49

1 Answers1

2

Your problem is the way you call limitRange. It's first argument needs to be a function, but you give it dweibull(shape = 2, scale = 1.12), which is not a function. It is, in fact, that causing the error:

dweibull(shape = 2, scale = 1.12)
# Error in dweibull(shape = 2, scale = 1.12) : 
#  argument "x" is missing, with no default

Turning that into a function works:

ggplot(data.frame(x = c(0, 2)), aes(x)) +
  stat_function(fun = dweibull,
                args = list(shape = 2, scale = 1.12)) +
  stat_function(
    fun = limitRange(function(z) dweibull(z, shape = 2, scale = 1.12), 0.0297, 0.1189),
    geom = "area",
    fill = "blue",
    alpha = 0.2
  ) 

An overall cleaner way would be to give limitRange a ... argument for fun:

limitRange <- function(fun, ..., min, max) {
  return(function(x) {
    y <- fun(x, ...)
    y[x < min  |  x > max] <- NA
    return(y)
  })
}

ggplot(data.frame(x = c(0, 2)), aes(x)) +
  stat_function(fun = dweibull,
                args = list(shape = 2, scale = 1.12)) +
  stat_function(
    fun = limitRange(dweibull, shape = 2, scale = 1.12, min = 0.0297,  max = 0.1189)
    geom = "area",
    fill = "blue",
    alpha = 0.2
  ) 

You will need to name the min and max arguments this way (and it may cause bugs if fun takes min and max arguments... more unique names might be better).

Gregor Thomas
  • 136,190
  • 20
  • 167
  • 294