Home > front end >  Customize ggplot2 behavior beyond themes
Customize ggplot2 behavior beyond themes

Time:10-06

I want to define a common style for all my plots, and I found that defining a custom theme is very useful. However, I would also like to define default values for variables that are not in themes, such as the size of lines and the widths of bars in geom_barplot, or expand in scale_y_continuous.

To be more specific, I defined my custom theme so that in barplots the x-axis should be at zero, so I set scale_y_continuous(expand=c(0,0)), but I have to do it "by hand" every time I call ggplot. Is there a way to redefine default values for this and other variables once and for all plots, similarly to what I can do with variables in themes?

CodePudding user response:

There are several ways of doing this, though to get the syntax as simple as mytheme would require a bit of work, including creating a new class to hold theme and scale elements, and over-riding the .gg method, which I don't personally think is worth the trouble:

make_mytheme <- function(scale, theme) {
  structure(list(scale = scale, theme = theme), class = 'mythemeclass')
}

` .gg` <- function(e1, e2) {
  e2name <- deparse(substitute(e2))
  if(inherits(e2, 'mythemeclass')) {
    e1 <- ggplot2:::add_ggplot(e1, e2$scale, e2name)
    return(ggplot2:::add_ggplot(e1, e2$theme, e2name))
  } else {
    return(ggplot2:::` .gg`(e1, e2))
  }
}

You can now create a theme that you can use which incorporates scale items and theme items:

mytheme <- make_mytheme(scale_y_continuous(expand = c(0, 0)), 
                        theme_bw(base_size = 20))

So, for example, if we had the following plot:

p <- ggplot(mtcars, aes(gear, mpg))   
  geom_bar(stat = 'summary', fun = mean)

p

enter image description here

We could just do:

p   mytheme

enter image description here

A simpler way would be to create a wrapper around ggplot itself:

my_ggplot <- function(...) {
  ggplot(...)   
  scale_y_continuous(expand = c(0, 0))  
  theme_bw(base_size = 20)
}

Which allows:

my_ggplot(mtcars, aes(gear, mpg))   
  geom_bar(stat = 'summary', fun = mean)

enter image description here

Changing the default line thickness of the various geoms can easily be done with similar wrappers, for example:

geom_thickline <- function(...) geom_line(..., size = 2)

Or, again, hacking the gg addition method:

thicken_lines <- function(size) {
  structure(list(size = size), class = 'thickener')
}

` .gg` <- function(e1, e2) {
  if(inherits(e2, 'thickener')) {
    e1$layers <- lapply(e1$layers, function(x) {
      x$aes_params <- c(x$aes_params, size = e2$size)
      x
    })
    return(e1)
  }
  ggplot2:::` .gg`(e1, e2)
}

Which allows:

ggplot(mtcars, aes(gear, mpg))   
  geom_line(stat = 'summary', fun = mean)  
  thicken_lines(3)

enter image description here

  • Related