5

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?

halfer
  • 19,824
  • 17
  • 99
  • 186
James
  • 1,164
  • 2
  • 15
  • 36
  • 2
    You might also try a more statistically based approach with Poisson errors. – IRTFM May 22 '18 at 16:27
  • 3
    What interpretation do you want the grey area to have if you just cut parts of it off? It wont' be a proper confidence interval any more. Without a proper constrained statistical model, you're just drawing a random shape at that point. Probably better to just leave it off. – MrFlick May 22 '18 at 17:51

2 Answers2

4
 ggplot(df, aes(x=x, y=y)) +
   geom_point() +
   geom_smooth() +
   coord_cartesian(ylim = c(0,200))
user1317221_G
  • 15,087
  • 3
  • 52
  • 78
  • Does this solve OP's issue? The gray CI falls below zero – CPak May 22 '18 at 16:17
  • 4
    yes, this does solve the OP's question and is a significantly simpler solution. This should be the top answer. – Nick Sep 02 '20 at 16:49
4

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

GGamba
  • 13,140
  • 3
  • 38
  • 47
  • You can use this option for y-axis (and similarly for x-axis if needed): `scale_y_continuous(limits = c(min_y,max_y), oob=squish)` – Remy Mar 22 '21 at 11:41