Search code examples
rggplot2widthbar-chartggproto

Change geom_bar width default to another default


What I want to do

I currently have a custom theme for my plots, and I want to have on top of that some predefined parameters for all type of plots. My first focus is on bar charts, where I want to change the default width.

The default width of geom_bar in ggplot2 is "By default, set to 90% of the resolution of the data." (http://ggplot2.tidyverse.org/reference/geom_bar.html).

I'd like to change that default to 75%. To be clear, I am not interested in changing it like this:

geom_bar(stat='identity', width=0.75)

Because that would mean I have to specify it everytime I create a bar chart. I want it to be the new default.

What I tried so far

I tried to change the width default using this:

update_geom_defaults("bar", list(width=0.75))

But then I get an error message: Error: Aesthetics must be either length 1 or the same as the data (964): width. I'm thinking this might be due to the fact that the width is calculated based on the resolution of the data, which is not yet there at the moment I call update_geom_defaults

Plus, I also realised that width is not part of the default aes of the bars :

GeomBar$default_aes
* colour   -> NA
* fill     -> "grey35"
* size     -> 0.5
* linetype -> 1
* alpha    -> NA

My questions are:

  • Where is that 90% default set?
  • Can I change it in any way?
  • If not, is there another way to pass a predefined set of parameters to all the geom_* functions?

Thanks !


Solution

  • The default is defined in GeomBar:

    GeomBar <- ggproto("GeomBar", GeomRect,
      required_aes = c("x", "y"),
    
      setup_data = function(data, params) {
        data$width <- data$width %||%
          params$width %||% (resolution(data$x, FALSE) * 0.9)  ## <- right here
        transform(data,
          ymin = pmin(y, 0), ymax = pmax(y, 0),
          xmin = x - width / 2, xmax = x + width / 2, width = NULL
        )
      },
    
      draw_panel = function(self, data, panel_params, coord, width = NULL) {
        # Hack to ensure that width is detected as a parameter
        ggproto_parent(GeomRect, self)$draw_panel(data, panel_params, coord)
      }
    )
    

    The marked line uses %||%, which is used to set a default in the event params$width is NULL (which is the default in geom_bar, NULL means "set it to something reasonable for me").

    There is no nice way like update_geom_defaults to change this. What you can do, is make your own geom_bar like this:

    geom_bar75 <- function (..., width = 0.75) {
      geom_bar(..., width = width)
    }
    

    This will work just fine in most cases, i.e. with a discrete x-axis (because the resolution is then 1). For more complicated cases you may need to adjust, or redefine GeomBar itself.

    ggplot(mpg, aes(class)) + geom_bar()
    ggplot(mpg, aes(class)) + geom_bar75()
    

    enter image description here