Search code examples
rggplot2loess

Set limits on loess line confidence interval shading in ggplot


I am having a problem with loess lines displaying properly in ggplot. I have several variables, none of which can go below zero e.g. heights, weights and abundances. I am trying to plot this data in ggplot with a loess line. Using some made up data:

library(ggplot2)

df <- as.data.frame(rep(1:7, each = 5))

df[,2] <- c(0,1,5,0,6,0,7,2,9,1,1,18,4,2,34,8,18,24,56,12,12,18,24,63,48,
       40,70,53,75,98,145,176,59,98,165)

names(df) <- c("x", "y")

ggplot(df, aes(x=x, y=y)) +
  geom_point() +
  geom_smooth() +
  scale_y_continuous(limits = c(-20,200))

enter image description here

This would be fine except that the shaded region showing the confidence intervals around the smoothed line goes below zero and a reviewer has pointed out that this is not possible and asked that I change it. I thought this could be easily done by setting the lower limit on the y axis to zero:

ggplot(df, aes(x=x, y=y)) +
  geom_point() +
  geom_smooth() +
  scale_y_continuous(limits = c(0,200))

enter image description here

But this makes part of the shaded area around the loess line dissapear. Is there a way to either make the plot work with the y axis limited to zero so that part of the shaded region is cut off, or to set a limit on the loess line in the first place so that it won't create a shaded region which goes below zero?


Solution

  • We can calculate override the ymin aes of a stat_smooth (note the difference with geom_smooth):

    ggplot(df, aes(x=x, y=y)) +
      geom_point() +
      stat_smooth(geom='ribbon', aes(ymin = ifelse(..ymin.. < 0, 0, ..ymin..)), 
                  alpha = .3) +
      geom_smooth(se = FALSE) +
      scale_y_continuous(limits = c(-20,200))
    #> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
    #> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
    

    Created on 2018-05-22 by the reprex package (v0.2.0).