4

I would like to make the y-axis of a bar chart symmetric, so that it's easier to see if positive or negative changes are bigger. Since otherwise this is a bit distorted. I do have working code although it's a bit clumsy and I thought it would be great if I could directly do this in the first ggplot() call. So as to say that ylim directly is symmetrical.

set.seed(123)
my.plot <- ggplot( data = data.table(x = 1:10,
                          y = rnorm(10,0, 2)), aes(x=x, y=y)) +
        geom_bar(stat="identity")

rangepull <- layer_scales(my.plot)$y
newrange <- max(abs(rangepull$range$range))
my.plot +
             ylim(newrange*-1, newrange)
M--
  • 25,431
  • 8
  • 61
  • 93
hannes101
  • 2,410
  • 1
  • 17
  • 40
  • I don't understand very well your question. No problem if your data set is defined before calling `ggplot()`, but you want to define the data inside the plotting function? Is it really needed? – R18 Jun 16 '17 at 14:00
  • This is just part of my MWE and not really an issue. Of course the data could be generated before as well. – hannes101 Jun 16 '17 at 14:18
  • 1
    So, just generate `data` object and then add to the `ggplot()` the code `+ ylim(1.05*(-max(abs(data$y))), 1.05*max(abs(data$y)))`. – R18 Jun 16 '17 at 14:25
  • 1
    If your concern is that you don't have a nice `mydata` object to work with (such as being the end of a long piping chain), use something like `mystartingdata %>% some_dplyr_verbs(...) %>% {ggplot(data = .) + geom_col(aes(x=x, y=y)) + ylim(1.05*(-max(abs(.$y))), 1.05*max(abs(.$y)))}`. The curly braces let you use the `.` pronoun throughout the `ggplot` call. – Brian Jun 16 '17 at 17:22

2 Answers2

1

What about this :

library(ggplot2)
library(data.table)
set.seed(123)

my.data = data.table(x = 1:10, y = rnorm(10,0, 2))

my.plot <- ggplot(data = my.data)+aes(x=x, y=y) +
  geom_bar(stat="identity")+ylim((0-abs(max(my.data$y))),(0+max(abs(my.data$y))))

my.plot
MBnnn
  • 308
  • 2
  • 13
  • What if we only have positive records? And other situations. This may or may not work. – M-- Jun 16 '17 at 14:04
  • I've made and edit (with abs() function), but if you've got only positve or only negative, then you will see than your data aren't symmetric ? Isn't the point ? – MBnnn Jun 16 '17 at 14:07
  • But it can be embedded in the code. Think about it a little bit. – M-- Jun 16 '17 at 14:10
  • But `ggplot` doesn't just take the max or min to define the limit of the y-axis. Therefore, I am extracting the values, if I would know how it is defined by ggplot, I could just use these. – hannes101 Jun 16 '17 at 14:17
  • But what do you want to do ? And I think that ggplot take the max and min to make the y-axis by default. I think I don't get what you want to do – MBnnn Jun 16 '17 at 14:21
  • @hannes101 ggplot considers expansion and min/max. Look at this [ticket](https://stackoverflow.com/questions/23710875/remove-extra-space-beyond-xlim-and-ylim). cc: MBnnn – M-- Jun 16 '17 at 14:39
1

You may want to consider using ceiling:

set.seed(123)
library(ggplot2)
library(data.table)

        dT <- data.table(x = 1:10, y = rnorm(10,0, 2))
        my.plot <- ggplot(dT, aes(x=x, y=y)) +
                   geom_bar(stat="identity") + 
                   ylim(-ceiling(max(abs(dT$y))), ceiling(max(abs(dT$y))))

This will give you:

 > my.plot

             https://i.stack.imgur.com/rMMzl.png

M--
  • 25,431
  • 8
  • 61
  • 93
  • Thanks, although I think the `ceiling` command doesn't make any difference. One of the issues of this approach is, that the data has to be defined beforehand. If, like in my case it's a intermediate result of a `merge`, it probably is easier to just go with the solution I am using in my initial post. – hannes101 Jun 16 '17 at 14:39