Search code examples
rggplot2weibull

Shading subregion under Weibull curve in R


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.


Solution

  • 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).