4.6 Building a New Theme
Building and modifying a theme in
ggplot2 is a key feature of the
ggplot2 package and system for building data graphics. The original base graphics system in R did not have a notion of a “theme” for how graphical elements are presented—users were left to individually customize each graphic without any clear way to programmatically implement shared elements across plots.
ggplot2 package implements the notion of a theme for its plots by allowing you to modify many different elements of a plot and to store all those modifications as a special “theme” object. Those elements that can be modified are documented in the help page
?theme, which documents the
The default theme for
ggplot2 is encapsulated by the
theme_gray() function. Like other elements in the
ggplot2 universe, themes can be “added” using the
+ operator to plot commands in order to change the look and feel of a plot. Adding a theme (either existing or custom built by you) will override elements of any default theme.
For example, here is a plot that uses the
library(ggplot2) ggplot(data = mtcars, aes(x = disp, y = mpg)) + geom_point() + theme_classic()
Notice how the look and the feel of the plot is substantially different from the default gray theme of
ggplot2. The key differences in the
theme_classic() setup are the background color (white instead of gray), the colors of the grid lines (none instead of white), and the presence of solid black x- and y-axes. Other elements are the same, like the plotting character (solid circle) and fonts.
Note that themes in
ggplot2 only allow you to modify the non-data elements of a plot. Things like the title, axis labels, background, etc. can be modified with a theme. If you want to change data elements, like the plotting symbol or colors, you can modify those things separately in their respective
4.6.1 Why Build a New Theme?
Why would one want to build a new theme? For many people, it is a matter of personal preference with respect to colors, shapes, fonts, positioning of labels, etc. Because plots, much like writing, are an expression of your ideas, it is often desirable to customize those plots so that they accurately represent your vision.
In corporate or institutional settings, developing themes can be a powerful branding tool. Plots that are distributed on the web or through marketing materials that have a common theme can be useful for reinforcing a brand. For example, plots made by the FiveThirtyEight.com web site have a distinct look and feel (see this article by Walt Hickey for one of many examples). When you see one of those plots you instinctively know that it is a “FiveThirtyEight” plot. Developing a theme for your organization can help to get others to better understand what your organization is about when it produces data graphics.
Another advantage of having a pre-programmed theme is that it removes the need for you to think about it later! One key reason why news organizations like FiveThirtyEight or the New York Times have common themes for their data graphics is because they are constantly producing those graphics on a daily basis. If every plot required a custom look and feel with a separate palette of colors, the entire process would grind to a halt. If you are in an environment where there is a need for reproducible graphics with a consistent feel, then developing a custom theme is probably a good idea. While using the default
ggplot2 theme is perfectly fine from a data presentation standpoint, why not try to stand out from the crowd?
4.6.2 Default Theme
As noted above,
ggplot2 has a default theme, which is
theme_gray(). This theme produces the familiar gray-background-white-grid-lines plot. You can obtain the default theme using the
x <- theme_get() class(x)
 "theme" "gg"
The object returned by
theme_get() is rather large so it’s not recommended to print it to the console. Notice that the object returned by
theme_get() is an S3 object of class
"gg". This is the kind of object you will need to create or modify in order to customize your theme.
You can modify the default theme by using the
theme_set() function and passing it a
theme object. For example, if we want all my plots to use the
theme_minimal() theme, we could do
new_theme <- theme_minimal() theme_set(new_theme)
Now your plots will use the
theme_minimal() theme without you having to specify it.
ggplot(data = mtcars, aes(disp, mpg)) + geom_point() + facet_grid( . ~ gear)
Quitting R will erase the default theme setting. If you load
ggplot2 in a future session it will revert to the default gray theme. If you’d like for
ggplot2 to always use a different theme (either yours or one of the built-in ones), you can set a load hook and put it in your
.Rprofile file. For example, the following hook sets the default theme to be
theme_minimal() every time the
ggplot2 package is loaded.
setHook(packageEvent("ggplot2", "onLoad"), function(...) ggplot2::theme_set(ggplot2::theme_minimal()))
Of course, you can always override this default theme by adding a theme object to any of your plots that you construct in
4.6.3 Creating a New Theme
Perhaps the easiest thing to start with when customizing your own theme is to modify an existing theme (i.e. one that comes built-in to
ggplot2). In case your are interested in thoroughly exploring this area and learning from others, there is also the
ggthemes package on CRAN which provides a number of additional themes for
Looking at the help page
?theme you’ll see that there are many things to modify. We will start simple here by illustrating the general approach to making theme modifications. We will begin with the
theme_bw() theme. This theme is a simple black and white theme that has little ornamentation and few features.
184.108.40.206 Modifying theme attributes
Suppose we want to make the default color for plot titles to be dark red. We can change just that element by adding a
theme() modification to the existing theme.
newtheme <- theme_bw() + theme(plot.title = element_text(color = "darkred"))
Note that in our call to
theme(), when we modify the
plot.title attribute, we cannot simply say
color = "darkred". This must be wrapped in a call to the
element_text() function so that the elements of
plot.title are appropriately modified. In the help page for
theme(), you will see that each attribute of a theme is modified by using one of four
element_text(): specify the display of text elements
element_line(): specify the display of lines (i.e. axis lines)
element_rect(): specify the display of borders and backgrounds
element_blank(): draw nothing
All of these functions work in the same way (although they contain different elements) and each of them returns a list of values inheriting from the class “element”. The
ggplot2 functions know how to handle objects of this class and will modify the theme of a plot accordingly.
Let’s change a few more things about our new theme. We can make the box surrounding the plot to look a little different by modifying the
panel.border element of the theme. First let’s take a look at what the value is by default.
List of 5 $ fill : logi NA $ colour : chr "grey20" $ size : NULL $ linetype : NULL $ inherit.blank: logi TRUE - attr(*, "class")= chr [1:2] "element_rect" "element"
You can see that this is an object of class
element_rect and there are 5 elements in this list, including the
linetype. These attributes have the same meaning as they do in the usual
We can modify the
color attribute to make it “steelblue” and modify the
size attribute to make it a little bigger.
newtheme <- newtheme + theme(panel.border = element_rect(color = "steelblue", size = 2))
Now let’s see what a typical plot might look like. The following is a plot of minutes played an shots attempted from the
worldcup dataset in the
library(faraway) ggplot(data = worldcup, aes(Time, Shots)) + geom_point() + ggtitle("World Cup Data") + newtheme
This may not be your idea of a great-looking theme, but it is certainly different! If we were to facet the data by
Position the theme attributes would extend to the individual panels, which is a nice thing to get for free.
ggplot(data = worldcup, aes(Time, Shots)) + geom_point() + facet_wrap(facets = ~ Position, ncol = 2) + ggtitle("World Cup Data") + newtheme
220.127.116.11 Complete themes
When using the
theme() function to modify specific elements of an existing theme, the default value for the argument
FALSE. This simply indicates, that the
theme() function is not returning a complete theme where every element is appropriately specified. Rather, it is just modifying the theme element that you specified.
complete = TRUE in the call to
ggplot2 that the
theme() function is returning a complete theme along the lines of
theme_bw(). In particular, all of the theme elements will inherit from the
blank element, meaning that there will be no values to “fall back” on in the event that you do not specify them. Setting
complete = TRUE only if you plan to specify every single theme element that is meaningful to you. If you are creating a brand new theme specific to you, then you may well be doing that. But if you are simply tweaking an existing theme, it’s appropriate to set
complete = FALSE.
Building a new theme allows you to customize the look and feel of a plot to match your personal preferences. It also allows you to define a consistent “branded” presentation of your data graphics that can be clearly identified with your organization or company.