8

Often in plots the Y axis value label is chopped off below the max value being plotted.

For example:

library(tidyverse)
mtcars %>% ggplot(aes(x=mpg, y = hp))+geom_point()

I know of scale_y_continous - but I can't figure out a smart way to do this. Maybe I'm just overthinking things. I don't wish to mess up the 'smart' breaks that are generated automatically.

I might try to go about this manually...

  mtcars  %>% ggplot(aes(x=mpg, y=hp, color=as.factor(carb)))+geom_point()  + scale_y_continuous(limits = c(0,375))

enter image description here

But this doesn't work like I mentioned above because of the 'smart breaks'. Is there anyway for me to extend the default break interval to 1 more, so that in this case it would be 400? Of course I would want this to be flexible for whatever dataset I am working with.

runningbirds
  • 6,235
  • 13
  • 55
  • 94

4 Answers4

14

You can use expand_limits() to increase the maximum y-axis value. You can also ensure that the maximum y-axis value is rounded up to the next highest value on the scale of the data, e.g., next highest tens value, next highest hundreds value, etc., depending on the whether the highest value in the data is within the tens, hundreds, etc.

For example, the function below finds the base 10 log of the maximum y value and rounds it down. This gives us the base ten scale of the maximum y value (e.g., tens, hundreds, thousands, etc.). It then rounds the maximum y-axis value up to the nearest ten, hundred, etc., that is higher than the maximum y value.

expandy = function(vec, ymin=NULL) {

  max.val = max(vec, na.rm=TRUE)
  min.log = floor(log10(max.val))

  expand_limits(y=c(ymin, ceiling(max.val/10^min.log)*10^min.log))
}

p = mtcars %>% ggplot(aes(x=mpg, y = hp)) +
  geom_point()

p + expandy(mtcars$hp)

p + expandy(mtcars$hp, 0)

Or, to make things a bit easier, you could set up the function so that the y-range data is collected directly from the plot:

library(gridExtra)

expandy = function(plot, ymin=0) {

  max.y = max(layer_data(plot)$y, na.rm=TRUE)
  min.log = floor(log10(max.y))

  expand_limits(y=c(ymin, ceiling(max.y/10^min.log)*10^min.log))
}

p = mtcars %>% ggplot(aes(x=mpg, y = hp)) +
  geom_point()

grid.arrange(p, p + expandy(p), ncol=2)

enter image description here

p = iris %>% ggplot(aes(x=Sepal.Width, y=Petal.Width)) +
  geom_point()

grid.arrange(p, p + expandy(p), ncol=2)

enter image description here

eipi10
  • 91,525
  • 24
  • 209
  • 285
  • dumb question, but how would I go about adding this to a theme? I'm sure I can look at it closely, but wondering if quick solution – runningbirds Dec 06 '18 at 21:59
  • Great function, feels like something that should be integrated within the package. – Brandon May 20 '20 at 07:03
2

Choosing a step for breaking the y axis you can use the ceiling() function

library(gridExtra)

p1 <- mtcars %>% ggplot(aes(x=mpg, y = hp)) + geom_point() 

p2 <- p1 +
  scale_y_continuous(
    limits = c(0, ceiling(max(mtcars$hp)/50)*50), 
    breaks = seq(0, ceiling(max(mtcars$hp)/50)*50, 50)
  ) 

p3 <- p1 + scale_y_continuous(
  limits = c(0, ceiling(max(mtcars$hp)/100)*100), 
  breaks = seq(0, ceiling(max(mtcars$hp)/100)*100, 100)
) 

grid.arrange(p1, p2, p3, ncol=3)

For the p2 the ste is 50 while for p3 the step is 100

enter image description here

Tiziano
  • 271
  • 1
  • 5
  • 9
0

Here a solution that allow any kind of numeric scales:

expandy <- function(y, base, v_min = NULL) {

  max.val <- max(y, na.rm = TRUE)

  expand_limits(
    y = c(
      v_min, 
      base * (max.val %/% base + as.logical(max.val %% base))
    )
  )

}
Captain Tyler
  • 500
  • 7
  • 19
0

here is a rather simple answer, just set one limit to NA:

mtcars %>% 
  ggplot(aes(x=mpg, y=hp, color=as.factor(carb))) + 
  geom_point() + 
  scale_y_continuous(limits = c(0, NA))
rrs
  • 9,615
  • 4
  • 28
  • 38