With any graphic in R, including a ggplot2 graphics, you are able to customize every aspect of the graphic. Here we will introduce some of the most commonly used customization options in ggplot2.
library("tidyverse")
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.1.4.9000 ✔ readr 2.1.5
✔ forcats 1.0.0 ✔ stringr 1.5.1
✔ ggplot2 3.5.1 ✔ tibble 3.2.1
✔ lubridate 1.9.3 ✔ tidyr 1.3.1
✔ purrr 1.0.2
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag() masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
To investigate different customization options, we will utilize the warpbreaks data set. Here is a default plot using these data:
So that we don’t have to copy-paste all the code plot every time, we saved the plot into the object g. This will allow us to add layers and customization by using g +.
16.1 Themes
Themes provide a different overall look of the graphic. There are a variety of built-in themes that can be accessed very quickly.
# Some built-in themesg +theme_bw()
g +theme_light()
g +theme_dark()
g +theme_minimal()
The default theme can be changed in a given R session using theme_set(). Let’s set the theme_bw() as the default theme for this session.
# Set the default themetheme_set(theme_bw())
16.2 Legend
The legend can quickly be removed or moved.
# Remove legendg +theme(legend.position ="none")
# Legend on bottomg +theme(legend.position ="bottom")
The legend can also be put inside the plot using x and y axis offsets, i.e. values between 0 and 1 that indicate, as a proportion of the x and y axis, where the legend should be located.
# Put legend inside the plotg +theme(legend.position =c(0.9, # x offset in (0,1) 0.8# y offset in (0,1)))
Warning: A numeric `legend.position` argument in `theme()` was deprecated in ggplot2
3.5.0.
ℹ Please use the `legend.position.inside` argument of `theme()` instead.
By default, the legend will be centered on the coordinates provided in legend.position.
# Put top right corner of legend at desired coordinatesg +theme(legend.position =c(0.9, 0.8),# put top right corner on coordinateslegend.justification =c(1, 1))
The legend justification can be utilized to quickly put a plot in a corner of the plotting area by setting the legend.position and legend.justification
# Put legend in the top rightg +theme(legend.position =c(1, 1),legend.justification =c(1, 1))
16.3 Labels
Labels can be modified in (at least) two ways: 1) adding the labs() function or 2) modifying the underlying data.
# Change labels using labs()g +labs(# Use aes() valuesx ="Tension",y ="Breaks",color ="Wool",shape ="Wool",# Add a titletitle ="Title",subtitle ="Subtitle",# Captioncaption ="Caption",tag ="Tag")
For those variables listed in aes(), you can change the underlying data.
# Change labels in datad <- warpbreaks |>rename(Wool ="wool",Tension ="tension",# Use backticks when including characters # not allowed in variable names`Number of Breaks`="breaks" )ggplot(d, aes(x = Tension,y =`Number of Breaks`, # use backticks with invalid variable namescolor = Wool,shape = Wool )) +geom_jitter(width =0.1, height =0)
16.4 Ticks
To modify the labels on ticks, you can change the labels in the plot.
You can also change the values on numeric axes which also changes the grid line locations.
# Change tick locations for numeric variablesg +scale_y_continuous(name ="Number of Breaks", # breaks =c(30, 50), # `breaks` is an argument of the function, not the warpbreaks variable namelimits =c(0, 70)) # we can also set limits using this function
16.5 Colors
Colors can be set for fill and color aesthetics. There are (at least) three ways to set colors. The first is to use preset names.
# Set colors by position using color nameg +scale_color_manual(values =c("red", # A"gold") # B )
# Set colors by name using color nameg +scale_color_manual(values =c("A"="red2", "B"="gold1") )
We can set the colors values using a HEX code which is a [hexidecimal] number from 0 to 255 for each of the red, green, and blue color channels. These hexidecimal codes were obtained from the ISU Color Brand page.
# Set colors by hexg +scale_color_manual(values =c("A"="#C8102E", # ISU Cardinal"B"="#F1BE48") # ISU Gold )
Set colors using RGB values. RGB values in R are specified as decimal values between 0 and 1 for the red, green, and blue color channels. Hexidecimal colors (as used above) are [hexidecimal] integer values from 0 to 255. So many times, you will see RGB values given as [decimal] integer values from 0 to 255. Below, we use the maxColorValue argument in the rgb() function to allow R to rescale to RGB values to (0,1).
Let’s reset the colors to always use ISU colors (be default).
# Resave plot using ISU colorsg <- g +scale_color_manual(values =c("A"="#C8102E", # ISU Cardinal"B"="#F1BE48") # ISU Gold )g
16.5.1 Palettes
A number of built in palettes can be used to quickly change color schemes. The ggplot2 package has a number of built in palettes. Here is a color palette that is colorblind friendly.
Set an RColorBrewer palette using the scale_color_brewer() function.
# Set RColorBrewer Accent paletteg +scale_color_brewer(palette ="Accent")
Scale for colour is already present.
Adding another scale for colour, which will replace the existing scale.
16.6 Shapes
When plotting points there are a variety of shapes to choose from:
?points
d <-data.frame(p =0:25) |>mutate(x = p %%6, # moduloy = p %/%6, # integer division, i.e. round down# Fix location for points with both fill and color aestheticsx =ifelse(p >20, (p+3) %%6, x),y =ifelse(p >20, (p+3) %/%6, y) )
Here are all the shapes available in R. Shapes in the top row have both a fill and color aesthetic while the remaining shapes only have a color aesthetic.
Shapes can be set manually by position or by name.
# Set shape by position (alphabetical ordering)g +scale_shape_manual(values =c(16, # A6)) # B
# Set shapes by nameg +scale_shape_manual(values =c("A"=15, "B"=5))
16.7 Lines
The information for lines is hidden within the help file for par (which is shorthand for graphical [par]ameters). Run the following help command, then scroll halfway through to the lty section.
Since our current plot does not have any lines, let’s add some lines to our plot.
# Calculate mean breaks fo reach tension-wool combinations <- warpbreaks |>group_by(tension, wool) |>summarize(breaks =mean(breaks), # Use `breaks` name so plot color will be consistent.groups ="drop" )# Add lines to plotg <- g +geom_line(data = s,aes(linetype = wool,group = wool))g
Set lines
g +scale_linetype_manual(values =c("A"="dotted","B"="dotdash" ))
16.7.1 Straight
A variety of straight lines can also be added to the plot
# Vertical line# Groups are set at integers starting at 1g +geom_vline(xintercept =1.5, linetype ="longdash")
# General line (doesn't make much sense in this plot)g +geom_abline(intercept =-20, slope =20, linetype ="longdash")
16.8 Annotate
To add text to the plot, we use the annotate() function with the “text” geom. The x and y coordinates here are exact coordinates rather than the (0,1) relative coordinates that were used for legend placement. Also, the discrete scale is integer-based, starting at 1.
# Add text annotationg +annotate(geom ="text",x =1.3, y =68, label ="Outliers?")
16.9 Summary
This page provides a variety of commonly used customization options for ggplot2 graphics. This is really just the beginning as there are many more things you can do.
If we put together everything from above, code to construct the graphic might look like the following.
# Pretty names for plottingd <- warpbreaks |>rename(Wool ="wool",Tension ="tension",`Number of Breaks`="breaks" ) |>mutate(Tension =fct_recode(Tension,Low ="L",Medium ="M",High ="H" ))# Calculate mean breaks fo reach tension-wool combinations <- d |>group_by(Tension, Wool) |>summarize(`Number of Breaks`=mean(`Number of Breaks`), .groups ="drop" )ggplot(d, aes(x = Tension, y =`Number of Breaks`,color = Wool,shape = Wool)) +geom_jitter(height =0,width =0.1,size =3# increase size so thumbnail looks good ) +geom_line(data = s,aes(linetype = Wool,group = Wool)) +scale_color_manual(values =c("A"="#C8102E", # ISU Cardinal"B"="#F1BE48")) +# ISU Goldscale_linetype_manual(values =c("A"="dotted","B"="dashed")) +scale_y_continuous(breaks =c(10, 30, 50), limits =c(0, 70)) +geom_hline(yintercept =45, linetype ="longdash",color ="grey") +annotate(geom ="text",x =1.3, y =68, label ="Outliers?" ) +labs(title ="Loom efficiency",subtitle ="Number of Breaks vs Tension and Wool Type" ) +theme_light()