Every year, I introduce hundreds of people to R, both in my live online courses and in university courses. In most of these, we use ggplot2, and invariably someone will raise their hand and ask whether it is possible to change the grey background to a different colour.
And it is! In this blog post, I’ll describe how to create a custom ggplot2 theme. In an upcoming post, I’ll then explain how to put it in an R package together with colour palettes, making your theme and palettes the default in ggplot2.
Changing the defaults
For this example, we’ll plot wind speed and temperature from the airquality data:
We can change the background colour, the grid, the font family, and all sorts of other settings using the theme function. Below is a rather extreme example, where we change many things at once; not because I recommend making all these changes, but just to see what is possible. I definitely don’t recommend using this particular combinations of colours - they were chosen to (hopefully) make it easier to see which part of the code affects which element of the plot:
ggplot(airquality, aes(Wind, Temp, colour =factor(Month))) +geom_point() +theme(# Change the background colour(s) and the border colour:panel.background =element_rect(fill ="pink",colour ="red",linewidth =2),plot.background =element_rect(fill ="darkblue"),legend.background =element_rect(fill ="white"),# Change the colours of the grid lines:panel.grid.major =element_line(colour ="cyan"),panel.grid.minor =element_line(colour ="yellow2",linetype ="dotted",linewidth =1),# Change fonts, font size, rotation, and colour of the text on the axis:axis.text =element_text(family ="Courier New",colour ="magenta",face ="bold",angle =45,hjust =1),axis.title =element_text(family ="Arial",colour ="skyblue",face ="italic",size =18) )
Creating a theme function
We can create a custom function with all of the above, which can then be added to our plots. For this, I’ll also add settings for text, which control the base size of text in the plot.
my_theme <-function(size =10) {theme(# Set base text size:text =element_text(size = size),# Change the background colour(s) and the border colour:panel.background =element_rect(fill ="pink",colour ="red",linewidth =2),plot.background =element_rect(fill ="darkblue"),legend.background =element_rect(fill ="white"),# Change the colours of the grid lines:panel.grid.major =element_line(colour ="cyan"),panel.grid.minor =element_line(colour ="yellow2",linetype ="dotted",linewidth =1),# Change fonts, font size, rotation, and colour of the text on the axis:axis.text =element_text(family ="Courier New",colour ="magenta",face ="bold",angle =45,hjust =1),axis.title =element_text(family ="Arial",colour ="skyblue",face ="italic",size =1.5*size) )}
We can now apply it to our plot, using different base font sizes:
Below is an example that is similar to a theme I created for a client who wanted a very clean look for their plots. Compared to the previous example, it uses some additional settings, like axis.ticks.x that controls the ticks on the x axis. element_blank() is used to remove things, e.g. the axis ticks, completely from the theme. The theme function has two arguments: size (base font size) and angle (rotation of axis text):