3

I am trying to modify the axes in ggplot2 so that it is one decimal point and has a label for every integer. However, I want to do it without an upper limit so that it will automatically adjust to data of different counts.

The difference between my question and the question posed here (that I was flagged as being a duplicate of) is that I need to make this work automatically for many different data sets, not just for a single one. It must automatically choose the upper limit instead of creating a fixed y-axis with breaks=(0,2,4,...). This question has been answered extremely well by @DidzisElferts below.

Here is my work:

library(data.table)
library(scales)
library(ggplot2)

mtcars <- data.table(mtcars)
mtcars$Cylinders <- as.factor(mtcars$cyl)
mtcars$Gears <- as.factor(mtcars$gear)
setkey(mtcars, Cylinders, Gears)
mtcars <- mtcars[CJ(unique(Cylinders), unique(Gears)), .N, allow.cartesian = TRUE]

ggplot(mtcars, aes(x=Cylinders, y = N, fill = Gears)) + 
               geom_bar(position="dodge", stat="identity") + 
               ylab("Count") + theme(legend.position="top") + 
               scale_x_discrete(drop = FALSE)

Cylinder Graph

As you can see, ggplot2 is plotting the axes with a decimal point and doing it every 2.5 automatically. I'd like to change that. Any way to do so?

Community
  • 1
  • 1
black_sheep07
  • 2,308
  • 3
  • 26
  • 40
  • I don't think you're going to get around having to infer specific break points/maximum y values from each data set you plot in order to do this. – joran May 29 '14 at 15:44
  • That requires far more interaction than I'd like. I was hoping that there is a way to do what I need it to do but it will automatically set an upper limit and then add in axis lines from there. – black_sheep07 May 29 '14 at 15:45
  • @joran see my answer for a solution – Jaap May 29 '14 at 16:31
  • @Jaap Your solution perfectly illustrates the correctness of my comment, namely that either specifying the breaks directly or calculating the max y value for each data set will likely be necessary. – joran May 29 '14 at 16:32
  • @joran You're right. When I read your comment again, I see your point. I probably jumped to fast to a conclusion after first reading (which was probably a bit to fast & superficial) – Jaap May 29 '14 at 16:39

2 Answers2

4
integer_breaks <- function(x)
  seq(floor(min(x)), ceiling(max(x)))

ggplot(mtcars, aes(x=Cylinders, y = N, fill = Gears)) + 
  geom_bar(position="dodge", stat="identity") + 
  ylab("Count") + theme(legend.position="top") + 
  scale_y_continuous(breaks=integer_breaks) +
  scale_x_discrete(drop = FALSE)
baptiste
  • 75,767
  • 19
  • 198
  • 294
3

Use scale_y_continuous(breaks=c(0,2,4,6,8,10)). So your plotting code will look like:

ggplot(mtcars, aes(x=Cylinders, y = N, fill = Gears)) + 
  geom_bar(position="dodge", stat="identity") + 
  ylab("Count") + theme(legend.position="top") + 
  scale_y_continuous(breaks=c(0,2,4,6,8,10)) +
  scale_x_discrete(drop = FALSE)

EDIT: Alternatively you can use scale_y_continuous(breaks=seq(round(max(mtcars$N),0))) in order to automatically adjust the scale to the maximum value of the y-variable. When you want the breaks more then 1 from each other, you can use for example seq(from=0,to=round(max(mtcars$N),0),by=2)

Jaap
  • 81,064
  • 34
  • 182
  • 193
  • I saw that in the `scale_y_continuous` documentation. I was hoping to find another way where I don't have to manually define the axis for each plot. – black_sheep07 May 29 '14 at 15:46
  • 1
    I tried out using the `scale_y_continuous(breaks=c(0,2,4,6,8,10,12))` command and found that `ggplot2` actually still adjusts to the proper upper limit, even if you set y limits that are too high. – black_sheep07 May 29 '14 at 15:53
  • @black_sheep07 but it probably doesn't do that when you set the y-limit to low; in that case my second method work better. I tested it on a plot I made this morning and on that plot it worked. – Jaap May 29 '14 at 15:57
  • True. Would there be any way to round it to the next even number? – black_sheep07 May 29 '14 at 16:00
  • you might try `seq(from=0,to=round(max(mtcars$N),0),by=2)` – Jaap May 29 '14 at 16:03