157

If you specify axis limits in ggplot the outlying points are removed. This is fine for points, but you might want to plot lines that intersect with the specified range, but ggplot's range or xlim/ylim methods removes these. Is there another way to specify the plot axis range without removing outlying data?

e.g.

require(ggplot2)
d = data.frame(x=c(1,4,7,2,9,7), y=c(2,5,4,10,5,3), grp=c('a','a','b','b','c','c'))
ggplot(d, aes(x, y, group=grp)) + geom_line()
ggplot(d, aes(x, y, group=grp)) + geom_line() + scale_y_continuous(limits=c(0,7))
ggplot(d, aes(x, y, group=grp)) + geom_line() + ylim(0,7)
0

3 Answers 3

250

Hadley explains this on pp. 99; 133 of his ggplot2 book (1st edition), or pp. 160 - 161 if you have the second edition.

The issue is that, as you say, limits inside the scale or setting ylim() causes data to be thrown away, as they are constraining the data. For a true zoom (keep all the data), you need to set the limits inside of the Cartesian coordinate system (or other coordinate systems https://ggplot2.tidyverse.org/reference/#section-coordinate-systems). For more see: http://docs.ggplot2.org/current/coord_cartesian.html

ggplot(d, aes(x, y, group=grp)) + 
    geom_line() + 
    coord_cartesian(ylim=c(0, 7))

enter image description here

4
  • 2
    What if coord_cartesian is not an option because I use geom_boxplot?
    – Everettss
    Commented Dec 18, 2017 at 8:03
  • 4
    coord_cartesian is still an option with geom_boxplot or other geoms.
    – eipi10
    Commented Apr 30, 2018 at 19:26
  • Yes, but can't figure out how to do horizontal boxplots since that requires coord_flip and you can't have two coords.
    – jtr13
    Commented Oct 5, 2018 at 15:28
  • 3
    Never mind, you can set the ylim's in coord_flip instead of coord_cartesian in that case.
    – jtr13
    Commented Oct 5, 2018 at 15:43
6

Just for completness here is the visual guide to this behaviour:

df <- data.frame(
  trt = c( 2, 3, 3.8, 5, 6),
  resp = c( 2.5, 3, 3.8, 3, 3.8),
  upper = c( 3, 3.3, 4.5, 3.3, 4.5),
  lower = c( 2, 2.4, 3.4, 2.4, 3.4)
)

p <- ggplot() +
  geom_point(data = df, 
                aes(x = trt, 
                    y = resp)) +
  geom_errorbar(data = df, 
                aes(x = trt, 
                    y = resp, 
                    ymin = lower, 
                    ymax = upper), 
                width = 0) +
  coord_flip() +
  theme_bw() +
  theme(plot.margin = margin(0.5, 3, 0.5, 0.5, "cm"))

p

enter image description here

p + 
  scale_y_continuous(limits = c(1, 4)) 

enter image description here

p + 
  coord_flip(ylim = c(1, 4))

enter image description here

p + 
  coord_flip(ylim = c(1, 4),
             clip = 'off') 

enter image description here

0

I know this is quite old, but thought I would throw in another solution using expand:

require(ggplot2)
d = data.frame(x=c(1,4,7,2,9,7), y=c(2,5,4,10,5,3), grp=c('a','a','b','b','c','c'))
ggplot(d, aes(x, y, group=grp)) + geom_line()
ggplot(d, aes(x, y, group=grp)) +
  geom_line() +
  scale_y_continuous(
    expand = expansion(add = c(2, -3)),
    breaks = c(0:7)
  )

Using expand

1
  • As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented Apr 28 at 0:27

Not the answer you're looking for? Browse other questions tagged or ask your own question.