2

I want to have an error bar for my geom_hline and thought that a geom_ribbon with opacity would look best. but i cant figure out how to make it reach the ends of the plot. I want the geom_ribbon to touch the sides of the plot as the geom_hline does. Here is the example code:

library('ggplot2')

x <- c(1,2,3,4,5,6,7,8,9,10)
y <- c(1,2,3,4,5,6,7,8,9,10)

data <- data.frame(x,y)

p1 <- ggplot(data,aes(x = x, y = y)) + geom_line() + geom_hline(yintercept=5)

p1 + geom_ribbon(aes(y = y[5],ymin = y[5]-0.5, ymax = y[5]+0.5, fill = 'red'), alpha = 0.4) 

enter image description here

Axeman
  • 32,068
  • 8
  • 81
  • 94
Fponken
  • 23
  • 3

3 Answers3

3

Use annotate with infinite x-values:

ggplot(data, aes(x, y)) + 
  geom_line() + 
  geom_hline(yintercept = 5) +
  annotate('ribbon', x = c(-Inf, Inf), ymin = 5 - 0.5, ymax = 5 + 0.5, 
           alpha = 0.4, fill = 'red')

enter image description here

If you need a legend, use geom_ribbon directly, like so:

ggplot(data, aes(x, y)) + 
  geom_line() + 
  geom_hline(yintercept = 5) +
  geom_ribbon(
    aes(x, y = NULL, ymin = ymin, ymax = ymax, fill = 'my_label'), 
    data.frame(x = c(-Inf, Inf), ymin = 5 - 0.5, ymax = 5 + 0.5),
    alpha = 0.4
  )
Axeman
  • 32,068
  • 8
  • 81
  • 94
  • If you do this, I don't believe you can add it to your legend easily – user2017023 Mar 11 '21 at 10:16
  • 1
    @user2017023, yes, but I think OP got their legend by mistake (i.e. they meant to use `fill = 'red'` outside `aes`, otherwise there's no point in labeling it `'red'`). To get a legend you can use `geom_ribbon` directly. I've added that to the answer. – Axeman Mar 11 '21 at 17:08
  • That's perfect. Thanks for responding to my comment 3 years later - I appreciate it! – user2017023 Mar 11 '21 at 21:03
1

There is no way in geom_hline() to set xlim, instead the horizontal line goes from end of the plot to the other. You can use geom_segment instead, which allows you to control the x-range and y-range of the line by specifying segment's start coordinate (x, y) and end coordinate (xend, yend)

This works:

library('ggplot2')

x <- c(1,2,3,4,5,6,7,8,9,10)
y <- c(1,2,3,4,5,6,7,8,9,10)

data <- data.frame(x,y)

p1 <- ggplot(data, aes(x = x, y = y)) + geom_line() + geom_segment(aes(x = x[1], xend = x[10], y = y[5], yend = y[5]))

p1 + geom_ribbon(aes(y = y[5],ymin = y[5]-0.5, ymax = y[5]+0.5, fill = 'red'), alpha = 0.4) 
hoggue
  • 147
  • 7
  • This works, but doesn't answer the question: _"I want the geom_ribbon to touch the sides of the plot as the geom_hline does."_ – Axeman Sep 20 '17 at 13:45
-1

Couple options:

1) Use geom_hline instead of geom_ribbon like so (probably best option):

p1 + geom_hline(yintercept = y[5], color = 'red', size = 8, alpha = 0.4)

enter image description here

2) Remove area between plot area and axis by adding scale_x_continuous(expand=c(0,0)) like so (credit to https://stackoverflow.com/a/22945857/5727278):

p1 + geom_ribbon(aes(y = y[5],ymin = y[5]-0.5, ymax = y[5]+0.5, fill = 'red'), alpha = 0.4) +
scale_x_continuous(expand=c(0,0))

enter image description here

Community
  • 1
  • 1
David Rubinger
  • 3,580
  • 1
  • 20
  • 29
  • Hi thanks for the answer! i like option 1 the best but the problem is that a line size of 8 dont equal y±0.4. The problem is ( i think when i looked around) that the size parameter is in inceh and seems to be fixed when dividing with 1/0.352777778 seems to work! [CREDIT TO: http://stackoverflow.com/questions/17311917/ggplot2-the-unit-of-siz](http://stackoverflow.com/questions/17311917/ggplot2-the-unit-of-size) – Fponken Dec 03 '16 at 14:41
  • Yes, the first option is unstable. and will change with scaling of the plot. – Axeman Sep 20 '17 at 08:53
  • I know this is very old, but as pointed out the first option is unstable. As far as I can tell, the second answer only works if you're only dealing with lines. If you are plotting points and want to add a horizontal line and associated ribbon, setting expand = c(0,0) will essentially cause the borders of your plot to truncate your points on either extreme. – user2017023 Mar 11 '21 at 10:16