201

How can I set the origin / interception of the y-axis and x-axis in ggplot2?

The line of the x-axis should be exactly at y=Z.

With Z=0 or another given value.

Jonas Stein
  • 6,826
  • 7
  • 40
  • 72

4 Answers4

266

xlim and ylim don't cut it here. You need to use expand_limits, scale_x_continuous, and scale_y_continuous. Try:

df <- data.frame(x = 1:5, y = 1:5)
p <- ggplot(df, aes(x, y)) + geom_point()
p <- p + expand_limits(x = 0, y = 0)
p # not what you are looking for

enter image description here

p + scale_x_continuous(expand = c(0, 0)) + scale_y_continuous(expand = c(0, 0))

enter image description here

You may need to adjust things a little to make sure points are not getting cut off (see, for example, the point at x = 5 and y = 5.

A5C1D2H2I1M1N2O1R2T1
  • 190,393
  • 28
  • 405
  • 485
  • 36
    I also needed to specify limits: `scale_x_continuous(expand = c(0, 0), limits = c(0,5))`, somehow without it it didn't work – JelenaČuklina Feb 12 '16 at 15:00
  • 6
    I think one more piece can be helpful, which is using something like `expand=expand_scale(mult=c(0,0.1))` so you still get the padding at the upper ends: https://stackoverflow.com/a/59056123/8400969 – Michael Roswell Nov 26 '19 at 17:15
36

Simply add these to your ggplot:

+ scale_x_continuous(expand = c(0, 0), limits = c(0, NA)) + 
  scale_y_continuous(expand = c(0, 0), limits = c(0, NA))

Example

df <- data.frame(x = 1:5, y = 1:5)
p <- ggplot(df, aes(x, y)) + geom_point()
p <- p + expand_limits(x = 0, y = 0)
p # not what you are looking for


p + scale_x_continuous(expand = c(0, 0), limits = c(0,NA)) + 
  scale_y_continuous(expand = c(0, 0), limits = c(0, NA))

enter image description here

Lastly, take great care not to unintentionally exclude data off your chart. For example, a position = 'dodge' could cause a bar to get left off the chart entirely (e.g. if its value is zero and you start the axis at zero), so you may not see it and may not even know it's there. I recommend plotting data in full first, inspect, then use the above tip to improve the plot's aesthetics.

stevec
  • 41,291
  • 27
  • 223
  • 311
  • is it also possible to build this into a new ggplot theme? – Bolle May 23 '20 at 08:21
  • 1
    @Bolle I’m not sure, but interested to find out as well, you could ask as a separate question and link to here – stevec May 23 '20 at 08:24
  • Link [here](https://stackoverflow.com/q/61969752/5783745) for future reference – stevec May 23 '20 at 16:03
  • 2
    Best answer imo for showing the necessity to include `limits`. – Bouncner Nov 10 '22 at 14:58
  • based on my experience, the benefit of adding `limits=c(0,NA)` is that makes "0" appear on the axis labels. Without it, the plot area will include 0, but zero generally doesn't appear on the axis labels – mac Apr 05 '23 at 23:00
  • Using `scale_y_continuous(expand = c(0, 0), limits = c(0, NA))` affected the upper limit of my graph. I had more success with simply `scale_y_continuous(limits = c(0, NA))` – Mateus Figueiredo Aug 22 '23 at 14:32
7

In the latest version of ggplot2, this can be more easy.

p <- ggplot(mtcars, aes(wt, mpg))
p + geom_point()
p+ geom_point() + scale_x_continuous(expand = expansion(mult = c(0, 0))) + scale_y_continuous(expand = expansion(mult = c(0, 0)))

enter image description here

See ?expansion() for more details.

Shixiang Wang
  • 2,147
  • 2
  • 24
  • 33
  • 2
    This only changes padding around data points, but does not help set axes origin to zero or other desired value. – Melkor.cz Sep 25 '20 at 08:37
4

Another option is using coord_cartesian with expand = FALSE. The limits are taken from the data or based on your limits. Here is a reproducible example:

df <- data.frame(x = 1:5, y = 1:5)

library(ggplot2)
p <- ggplot(df, aes(x, y)) + geom_point()
p <- p + expand_limits(x = 0, y = 0)
p + coord_cartesian(expand = FALSE)

Created on 2022-11-26 with reprex v2.0.2

You could also specify the limits in coord_cartesian directly like this:

df <- data.frame(x = 1:5, y = 1:5)

library(ggplot2)
p <- ggplot(df, aes(x, y)) + geom_point()
p + coord_cartesian(expand = FALSE, xlim = c(0, NA), ylim = c(0, NA))

Created on 2022-11-26 with reprex v2.0.2

Quinten
  • 35,235
  • 5
  • 20
  • 53