Adding ggplot themes and color palettes to a package

At work, I've developed an internal package to standardize some analysis across the team. Mostly this consists of commonly used functions. I'd also like to add a few ggplot themes and color palettes to this package, but these aren't functions, they're objects.

For example:

my_palette <- c('blue', 'black', 'red')
my_theme <- theme_bw() + theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

Right now, I just define these at the top of every relevant analysis and then reference them in ggplot:

ggplot(iris) +
  geom_point(aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  scale_color_manual(values = my_palette) +
  my_theme

Is there any good way to store objects like this in a package so I can avoid these repetition and also make sure these are standard across the team?

Everything in R is an object, including functions, so I don't think you need to do anything special to handle non-function objects in packages. For example, see MASS::abbey, which is just a numeric vector.

That said, for consistency on the themes, I think it makes sense to make them a function, just like theme_bw(). It will be less confusing to end-users, wondering why they need () after theme_bw but not my_theme. This is partially covered here:
http://ggplot2.tidyverse.org/articles/extending-ggplot2.html

But I think this blog post covers the details a little better:

1 Like

Yes, you can use ggplot2::theme_set() to set the default theme. To set default color palettes I think the best way to do it is to redefine the default scale functions to use the defaults you want.

If you want to have your internal package automatically set the default color scales and theme you can do so by setting them in .onAttach. This will change the defaults automatically anytime your package is attached with library(), so the results will be reproducible in the future. This code assumes ggplot2 is in your internal packages Depends, and you need to assign the scales in the global (rather than package) environment.

.onAttach <- function(pkgname, libname) {
  my_palette <- c('blue', 'black', 'red')
  my_theme <- theme_bw() + theme(axis.text.x = element_text(angle = 90, vjust = 0.5))
  theme_set(my_theme)

  assign("scale_colour_discrete", function(..., values = my_palette) scale_colour_manual(..., values = values), globalenv())
  assign("scale_fill_discrete", function(..., values = my_palette) scale_fill_manual(..., values = values), globalenv())
}

With this done you the results will be automatically used after you attach your internal package.


library(myinternalpkg)
#> Loading required package: ggplot2
ggplot(iris) +
    geom_point(aes(x = Sepal.Length, y = Sepal.Width, color = Species))

9 Likes

Thanks for the responses, this makes a lot of sense. I'm going to try these out!

Since you're created a package you can create a script for which your co-workers will use to reference the themes you've set up already.

I usually call the script global.R, in which I put:

# global script
library(ggplot2)
my_palette <- c('blue', 'black', 'red')
my_theme <- theme_bw() + theme(axis.text.x = element_text(angle = 90, vjust = 0.5))

Then in my script I do

library(ggplot2)
source('global.R')
# Then you can reference the pre built options without rewriting them over and over on scripts
ggplot(iris) +
  geom_point(aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  scale_color_manual(values = my_palette) +
  my_theme

This helps with helper functions as well so you're script won't get too lengthy