The Grammar of Graphics in R (ggplot2)

11 May, 2022

By: Murray Logan

This Tutorial has been thrown together a little hastily and is therefore not very well organised - sorry! Graphical features are demonstrated either via tables of properties or as clickable graphics that reveal the required R code. Click on a graphic to reveal/toggle the source code or to navigate to an expanded section.

This tutorial is intended to be viewed sequentially. It begins with the basic ggplot framework and then progressively builds up more and more features as default elements are gradually replaced to yeild more customized graphics.

Having said that, I am going to start with a sort of showcase of graphics which should act as quick navigation to entire sections devoted to the broad series of graphs related to each of the featured graphics. I have intentionally titled each graph according to the main feature it encapsulates rather than any specific functions that are used to produce the features as often a single graphic requires a combination of features and thus functions. Furthermore, the grammar of graphics specifications are sufficiently unfamiliar to many that the relationships between the types of graphical features a researcher wishes to produce and the specific syntax required to achieve the desired result can be difficult to recognise.

Each graphic is intended to encapsulate a broad series of related graph types.

The Grammar of Graphics

The Grammar of Graphics was first introduced/presented by Wilkinson and Wills (2006) as a new graphics philosophy that laid down a series of rules to govern the production of quantitative graphics. Essentially the proposed graphics infrastructure considers a graphic as comprising a plot (defined by a coordinate system, scales and panelling) over which one or more data layers are applied.

ggplot() +                          # required
    geom_*(                         # required
        data = <DATA>,              # required - <DATA> is a data frame
        mapping = aes(<MAPPING>),   # required - map variables to scales
        stat = <STAT>,              # optional - map variables to geoms
        position = <POSITION>) +    # optional - adjustments to overlapping geoms
    coord_*() +                     # optional - specify coordinate system
    scale_*() +                     # optional - visual appearence of scales
    facet_*() +                     # optional - subplots
    theme_*()                       # optional - overal appearence

Each layer is defined as:

  • the data - a data frame
  • mapping specifications that establish the visual aesthetics (colour, line type and thickness, shapes etc) of each variable
  • statistical methods that determine how the data rows should be summarised (stat)
  • geometric instructions (geom) on how each summary should be represented (bar, line, point etc)
  • positional mechanism for dealing with overlapping data (position)

The visual aspects of all the graphical features are then governed by themes.

Following a very short example, the next section will largely concentrate on describing each of the above graphical components. Having then established the workings of these components, we can then put them together to yield specific graphics.

Hadley Wickham’s interpretation of these principals in an R context is implimented via the ggplot2 package. In addition the following packages are also commonly used alongside ggplot so as to expand on the flexibility etc.

  • grid
  • gridExtra
  • scales
  • patchwork
  • tidyverse - which is actually a collection of packages that make up the tidyverse ecosystem.

To help illustrate graphical routines and techniques, this tutorial will make use of a number of data sets - most of which are distributed with base R or else one of the tidyverse _packages. The first of these motivating datasets is a built in data set (BOD) that records temporal changes (days) in biochemical oxygen demand (mg/l).

BOD

The biochemical oxygen demand (BOD) data set comprises of just two variables (demand: a numeric vector representing biochemical oxygen demand (mg/l) and Time: a numeric vector representing the time associated with the demand measurement). It was originally published in a master thesis in the late 1960’s and has since become a standard example data set on which to demonstrate various statistical techniques.

head(BOD)
##   Time demand
## 1    1    8.3
## 2    2   10.3
## 3    3   19.0
## 4    4   16.0
## 5    5   15.6
## 6    7   19.8
glimpse(BOD)
## Rows: 6
## Columns: 2
## $ Time   <dbl> 1, 2, 3, 4, 5, 7
## $ demand <dbl> 8.3, 10.3, 19.0, 16.0, 15.6, 19.8

CO2

The CO2 data set represents the CO₂ uptake (uptake: μmol/m²) of twelve individual Echinochloa crus-galli plants (Plant) from two locations (Type) and two temperature treatments (Treatment) in response to a range of ambient carbon dioxide concentration (conc: ml/l).

head(CO2)
##   Plant   Type  Treatment conc uptake
## 1   Qn1 Quebec nonchilled   95   16.0
## 2   Qn1 Quebec nonchilled  175   30.4
## 3   Qn1 Quebec nonchilled  250   34.8
## 4   Qn1 Quebec nonchilled  350   37.2
## 5   Qn1 Quebec nonchilled  500   35.3
## 6   Qn1 Quebec nonchilled  675   39.2
glimpse(CO2)
## Rows: 84
## Columns: 5
## $ Plant     <ord> Qn1, Qn1, Qn1, Qn1, Qn1, Qn1, Qn1, Qn2, Qn2, Qn2, Qn2, Qn2, …
## $ Type      <fct> Quebec, Quebec, Quebec, Quebec, Quebec, Quebec, Quebec, Queb…
## $ Treatment <fct> nonchilled, nonchilled, nonchilled, nonchilled, nonchilled, …
## $ conc      <dbl> 95, 175, 250, 350, 500, 675, 1000, 95, 175, 250, 350, 500, 6…
## $ uptake    <dbl> 16.0, 30.4, 34.8, 37.2, 35.3, 39.2, 39.7, 13.6, 27.3, 37.1, …

Diamonds

The diamonds data set comprises a set of attributes from a large number (~54,000) of diamonds. The most relevant attributes are:

  • carat - weight of the diamond
  • cut - quality of the cut
  • clarity - standard measurement of how clear the diamond is (on a clarity scale)
  • price - price in $US
head(diamonds)
## # A tibble: 6 × 10
##   carat cut       color clarity depth table price     x     y     z
##   <dbl> <ord>     <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
## 1  0.23 Ideal     E     SI2      61.5    55   326  3.95  3.98  2.43
## 2  0.21 Premium   E     SI1      59.8    61   326  3.89  3.84  2.31
## 3  0.23 Good      E     VS1      56.9    65   327  4.05  4.07  2.31
## 4  0.29 Premium   I     VS2      62.4    58   334  4.2   4.23  2.63
## 5  0.31 Good      J     SI2      63.3    58   335  4.34  4.35  2.75
## 6  0.24 Very Good J     VVS2     62.8    57   336  3.94  3.96  2.48
glimpse(diamonds)
## Rows: 53,940
## Columns: 10
## $ carat   <dbl> 0.23, 0.21, 0.23, 0.29, 0.31, 0.24, 0.24, 0.26, 0.22, 0.23, 0.…
## $ cut     <ord> Ideal, Premium, Good, Premium, Good, Very Good, Very Good, Ver…
## $ color   <ord> E, E, E, I, J, J, I, H, E, H, J, J, F, J, E, E, I, J, J, J, I,…
## $ clarity <ord> SI2, SI1, VS1, VS2, SI2, VVS2, VVS1, SI1, VS2, VS1, SI1, VS1, …
## $ depth   <dbl> 61.5, 59.8, 56.9, 62.4, 63.3, 62.8, 62.3, 61.9, 65.1, 59.4, 64…
## $ table   <dbl> 55, 61, 65, 58, 58, 57, 57, 55, 61, 61, 55, 56, 61, 54, 62, 58…
## $ price   <int> 326, 326, 327, 334, 335, 336, 336, 337, 337, 338, 339, 340, 34…
## $ x       <dbl> 3.95, 3.89, 4.05, 4.20, 4.34, 3.94, 3.95, 4.07, 3.87, 4.00, 4.…
## $ y       <dbl> 3.98, 3.84, 4.07, 4.23, 4.35, 3.96, 3.98, 4.11, 3.78, 4.05, 4.…
## $ z       <dbl> 2.43, 2.31, 2.31, 2.63, 2.75, 2.48, 2.47, 2.53, 2.49, 2.39, 2.…

df

This is a purely ficticious and fabricated example that is intended to provide a very small example data set.

df <- data.frame(x = c(3, 1, 5), y = c(2, 4, 6), z = c('a', 'b', 'c'))
x y z
3 2 a
1 4 b
5 6 c

Iris

The iris data set is a famous example data set that comprises the measurements (cm) of sepal and petal dimensions for three species of iris (Iris setosa, versicolor, and virginica).

  • Sepal.Length - length (cm) of sepals
  • Sepal.Width - width (cm) of sepals
  • Petal.Length - length (cm) of petals
  • Petal.Width - width (cm) of petals
  • Species - iris species
head(iris)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa
## 6          5.4         3.9          1.7         0.4  setosa
glimpse(iris)
## Rows: 150
## Columns: 5
## $ Sepal.Length <dbl> 5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9, 5.4, 4.…
## $ Sepal.Width  <dbl> 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.…
## $ Petal.Length <dbl> 1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.…
## $ Petal.Width  <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.…
## $ Species      <fct> setosa, setosa, setosa, setosa, setosa, setosa, setosa, s…

Faithfuld

2d density estimate of Old Faithful data

  • eruptions - eruption time (mins)
  • waiting - waiting time until next eruption (mins)
  • density - 2d density estimate
head(faithfuld)
## # A tibble: 6 × 3
##   eruptions waiting density
##       <dbl>   <dbl>   <dbl>
## 1      1.6       43 0.00322
## 2      1.65      43 0.00384
## 3      1.69      43 0.00444
## 4      1.74      43 0.00498
## 5      1.79      43 0.00542
## 6      1.84      43 0.00574
glimpse(faithfuld)
## Rows: 5,625
## Columns: 3
## $ eruptions <dbl> 1.600000, 1.647297, 1.694595, 1.741892, 1.789189, 1.836486, …
## $ waiting   <dbl> 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, …
## $ density   <dbl> 0.0032161588, 0.0038353752, 0.0044355478, 0.0049776139, 0.00…

Warpbreaks

The warpbreaks dataset comprises of the number of warp breaks per loom for two different types of wool under three different tensions.

  • breaks - the number of warp breaks
  • wool - the type of wool (A or B)
  • tension - the level of tension (L: low, M: medium, H: high)
head(warpbreaks)
##   breaks wool tension
## 1     26    A       L
## 2     30    A       L
## 3     54    A       L
## 4     25    A       L
## 5     70    A       L
## 6     52    A       L
glimpse(warpbreaks)
## Rows: 54
## Columns: 3
## $ breaks  <dbl> 26, 30, 54, 25, 70, 52, 51, 26, 67, 18, 21, 29, 17, 12, 18, 35…
## $ wool    <fct> A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A,…
## $ tension <fct> L, L, L, L, L, L, L, L, L, M, M, M, M, M, M, M, M, M, H, H, H,…

The following very simple graphic will be used to illustrate the general ggplot template outlined above by explicitly stating many of the default specifications. It will use a cartesian coordinate system, continuous axes scales, a single facet (panel) and then define a single layer with a dataframe (BOD), with red points, identity (no summarising) statistic visualised as a point geometric.

p <- ggplot() +                                # initialise ggplot 
    layer(data = BOD,                          # data.frame
          mapping = aes(y = demand, x = Time), # define x and y variables
          stat = "identity",                   # use raw input data
          geom = "point",                      # plot data as points
          position = "identity",               # how to handle overlap data
          params = list(na.rm = TRUE),         # additional params for stat
          show.legend = FALSE                  # whether include a legend
          )+ 
    layer(data = BOD,                          # data.frame
          mapping = aes(y = demand, x = Time), # define x and y variables
          stat = "identity",                   # use raw input data
          geom = "line",                       # plot data as a line
          position = "identity",               # how to handle overlap data
          params = list(na.rm = TRUE),         # additional params for stat
          show.legend = FALSE                  # whether include a legend
          ) +
    coord_cartesian() +                        # cartesian coordinates
    scale_x_continuous() +                     # continuous x axis
    scale_y_continuous()                       # continuous y axis
p                                              # print the plot

Conveniently, much of the default specifications can be omitted. Hence the above can also be entered as:

p <- ggplot(data = BOD,                        # initialise ggplot 
            map = aes(x = Time, y = demand)) + # define x and y variables
    geom_point() +                             # add points
    geom_line()                                # add lines
p                                              # print the plot

Note the following important features of the grammar of graphics as implemented in R:

  • the order in which each of the major components in the first code snippet were added is unimportant. They each add additional information to the overall graphical object. The object itself is evaluated as a whole when it is printed. For example, scales can be defined before layers.

    Explore

    The following both alter the x axis to a log (base 10) scale. Note how both expressions yield the same outcome.

    p <- ggplot(data = BOD,                      
                map = aes(x = Time, y = demand)) + 
        geom_point() +                            
        geom_line() +
        scale_x_log10()
    p                                           

    p <- ggplot(data = BOD,                      
                map = aes(x = Time, y = demand)) + 
        scale_x_log10() +
        geom_point() + 
        geom_line() 
    p                                           

  • multiple layers are laid down in the order that they appear in the statement. In the example above, the lines are drawn over the top of the points.

    Explore

    The following define points and lines in different orders. Note how the points appear under the line in the left hand figure and over the line in the right hand figure.

    p <- ggplot(data = BOD,                      
                map = aes(x = Time, y = demand)) + 
        geom_point(color = 'red', size=5) +                            
        geom_line()                              
    p                                           

    p <- ggplot(data = BOD,                      
                map = aes(x = Time, y = demand)) + 
        geom_line() +
        geom_point(color = 'red', size=5) 
    p                                           

  • layers can be defined either with the layers function, or more conveniently (as illustrated in the shorter, second code snippet), via a geom_* function or stat_* function.

    Explore

    The following both specify a single layer (line). The left hand figure uses the geom_line _function with the stat = 'identity argument and the right hand figure uses the stat_identity function with the geom = 'line' argument. Note, identity just means multiple by 1 (i.e. do nothing). The default stat for geom_line is identity and therefore it is not necessary to provide this argument - in this case it was purely used for illustrative purposes.

    p <- ggplot(data = BOD,                      
                map = aes(x = Time, y = demand)) + 
        geom_line(stat = 'identity')
    p                                           

    p <- ggplot(data = BOD,                      
                map = aes(x = Time, y = demand)) + 
        stat_identity(geom = 'line')
    p                                           

  • the data and mapping used by geom_* and stats_* functions can inherit mapping aesthetics from the main ggplot() function.

    Explore

    The following figures both generate a plot with both points and a line. In the left hand side syntax, geom_point and geom_line inherit the data and aesthetic mappings from the ggplot function. In the right hand side syntax, the two geoms specify the data and aesthetic mappings themselves. Whilst in this case it does lead to code duplication, in other cases, it does permit different sources of data to be integrated together into a single graphic.

    p <- ggplot(data = BOD,                      
                map = aes(x = Time, y = demand)) + 
        geom_line() +
        geom_point()
    p                                           

    p <- ggplot() +
        geom_line(data = BOD,                      
                  map = aes(x = Time, y = demand)) +
        geom_point(data = BOD,
                   map = aes(x = Time, y = demand))
    p                                           

  • the ggplot() function along with the other building functions work together to create a set of instructions that determine how a graph is to be constructed. In the examples above, these instructions are stored in a variable (which we arbitrarily assigned the name p). The graph is not actually generated until the print method is called on this object. Recall that in R, entering the name of an object is the same as running the print function on this object.

    Explore

    In the following figures, the plotting instructions will be built up in multiple stages.

    • the first stage of both examples stores the ggplot initialisation (including specification of the data and aesthetic mapping).
    • the second stage of the left hand syntax adds instructions for including two data layers (line and points). Finally, the left hand syntax then uses prints the full set of plotting instructions (which enacts the generation of the plot).
    • the second stage of the right hand syntax adds instructions for including a single layer (line) and in the final stage, instructions for including a point layer are added to the instruction set sent to print.
    • note, unlike for the left hand side syntax, the stored set of instructions on the right hand side do not contain the instructions for including the points layer - they are only added at the time of printing
    p <- ggplot(data = BOD,                      
                map = aes(x = Time, y = demand))  
    p <- p + geom_line() +
        geom_point()
    p                                           

    p <- ggplot(data = BOD,                      
                map = aes(x = Time, y = demand))  
    p <- p + geom_line()
    p + geom_point()                                          

In all of the examples so far, you might have noticed that we stored the plotting instructions in an arbitrary variable (p) prior to printing (generating the plot). Although it is not necessary to store the instructions (we can just accumulate the instructions and print in a single expression), storing sets of instructions do allow the instruction set to be duplicated or altered. This is particularly useful when you have a need to produce two similar and complex plots.

Since this is a tutorial, it will endeavour to focus on a very small set of concepts at any one time. To that end, most of the examples in a section will feature slight variations of a common snippet of code. Typically, there will be a single common code block that initialises a fairly generic plot followed by a series of modifications/additions that highlight different plotting routines or options.

In an attempt to illustrate the use of ggplot for elegant graphics, we will drill down into each of the plot and layer specifications.

Layers (geoms and stats)

Overview

Although the geoms and thus layers are amongst the last features to be constructed by the system, the data and aesthetic features of the data impact on how the coordinate system, scales and panelling work. Therefore, we will explore the geoms first.

Geometric objects (geoms) are visual representations of observations. For example, there is a geom to represent points based on a set of x,y coordinates. All graphics need at least one geom and each geom is mapped to its own layer. Multiple geoms can be added to a graphic and the order that they are added to the expression determines the order that their respective layer is constructed.

When a ggplot expression is being evaluated, geoms are coupled together with a stat_ function. This function is responsible for generating data appropriate for the geom. For example, the stat_boxplot is responsible for generating the quantiles, whiskers and outliers for the geom_boxplot function.

In addition to certain specific stat_ functions, all geoms can be coupled to a stat_identity function. In mathematical contexts, identity functions map each element to themselves - this essentially means that each element passes straight through the identity function unaltered. Coupling a geom to an identity function is useful when the characteristics of the data that you wish to represent are present in the data frame. For example, your dataframe may contain the x,y coordinates for a series of points and you wish for them to be used unaltered as the x,y coordinates on the graph. Moreover, your dataframe may contain pre-calculated information about the quantiles, whiskers and outliers and you wish these to be used in the construction of a boxplot (rather than have the internals of ggplot perform the calculations on raw data).

Since geom_ and stats_ functions are coupled together, a geometric representation can be expressed from either a geom_ function OR a stats_ function. That is, you either:

  • specify a geom_ function that itself calls a stat_ function to provide the data for the geom function.

    ggplot(CO2) + geom_smooth(aes(x = conc, y = uptake), stat = "smooth")
  • specify a stat_ function that itself calls a geom_ function to visually represent the data..

    ggplot(CO2) + stat_smooth(aes(x = conc, y = uptake), geom = "smooth")

It does not really make any difference which way around you do this. For the remainder of this tutorial, we will directly engage the geom_ function for all examples.

The geom_ functions all have numerous arguments, many of which are common to all geoms_.

  • data - the data frame containing the data. Typically this is inherited from the ggplot function.

  • mapping - the aesthetic mapping instructions. Through the aesthetic mapping the aesthetic visual characteristics of the geometric features can be controlled (such as colour, point sizes, shapes etc). The aesthetic mapping can be inherited from the ggplot function. Common aesthetic features (mapped via a aes function) include:

    • alpha - transparency
    • colour - colour of the geometric features
    • fill - fill colour of geometric features
    • linetype - type of lines used in geometric features (dotted, dashed, etc)
    • size - size of geometric features such as points or text
    • shape - shape of geometric features such as points
    • weight - weightings of values
  • stat - the stat_ function coupled to the geom_ function

  • position - the position adjustment for overlapping objects

    • identity - leave objects were they are:
    • dodge - shift objects to the side to prevent overlapping
    • stack - stack objects on top of each other
    • fill - stack objects on top of each other and standardize each group to equal height
  • show.legend - whether a legend should be included

  • inherit.aes - whether to override any aesthetics from the ggplot function

The above characteristics that can be aesthetically mapped to data variables, can alternatively be set directly. For example, in the left hand code snippet below, the colour of the points is determined by the value of the specified variable. However, in the right hand code snippet, the colour of the points is set to be red. Notice, that in this later instance, the colour is specified outside of the aesthetic (aes) function.

ggplot(data = CO2,                      
            map = aes(x = conc, y = uptake)) +
    geom_point(aes(colour = Type))                                  

ggplot(data = CO2,      
            map = aes(x = conc, y = uptake)) +
    geom_point(colour = "red")                                           

The above figure (left side) illustrated the use of aesthetics to highlight different groups (or series) within the data (Type in that case). For some geoms it is important that they be able to operate on a single series of data to avoid strange artefacts. The next two figures will include a layer of lines. In the left hand figure, the lines are drawn across a single series (group) yielding a nonsense pattern. This is addressed in the right hand figure which specifies that separate lines should be drawn for each Plant (each plant is its own series or group).

ggplot(data = CO2,                      
            map = aes(x = conc, y = uptake)) +
    geom_line()                                  

ggplot(data = CO2,      
            map = aes(x = conc, y = uptake)) +
    geom_line(aes(group = Plant))                                           

In the above right, the series are defined by the group aesthetic. Alternatively, we could have mapped Plant to one of the other aesthetics (such as colour, linetype etc), in which case, each line would have a different visual appearance and a legend would have also been included.

Currently, there are a large number of available geoms_ and stat_ functions within the ggplot system. This tutorial is still a work in progress and therefore does not include all of them - I have focused on the more commonly used ones.

Primitive geoms

Primitive geoms are simple plotting shapes that typically represent direct mapping of data variables to the shapes - that is, they do not require specific stat functions. Hence, all primitive geoms use stat_identity. Nevertheless, it is possible to have the shapes mapped via alternative stats functions is appropriate (see points).

Blank

Although this might seem pointless, it can be useful for forcing axes scales to conform to a particular format - since axes scales are determined by the first layer (which can be blank) defined in the sequence of expressions.

To help illustrate this, I will introduce a fabricated data set comprising the length (mm) of 10 day old frog tadpoles incubated at three different temperatures (Low, Medium, High).

tadpole <- tribble(
    ~length, ~temp,
    2.1,     "Low",
    2.0,     "Low",
    1.8,     "Low",
    2.2,     "Medium",
    2.3,     "Medium",
    2.3,     "Medium",
    2.5,     "High",
    2.7,     "High",
    2.8,     "High",
    ) %>%
    mutate(temp = factor(temp))

Now imagine you wish to produce a scatterplot (with length mapped to the y-axis and day mapped to the x-axis) to explore these data. Since although temp is categorical, it is ordered, we would also like to plot a line representing the overall trend in tadpole length in relation to temperature. Doing so would introduce one of two problems:

  • lines can only be plotted when both x and y are mapped to continuous variables
  • in order to plot a line, we would need to convert temperature into a numeric variable in some way, however doing so would mean that the axes labels loose their meaning.

Using a geom_blank allows us to define a line and maintain useful axes labels. The second and third examples below will illustrate the problem and solution respectively.

Feature geom stat position Aesthetic parameters / Notes Example plot
Blank layer _blank _identity identity x,y

ggplot(data=tadpole, aes(y = length, x = temp)) +
    geom_blank()
Blank layer _blank _summary identity x,y

ggplot(data=tadpole, aes(y = length, x = as.numeric(temp))) +
    geom_line(stat = 'summary', fun = mean) 
Blank layer _blank _summary identity x,y

ggplot(data=tadpole, aes(y = length, x = temp))+
    geom_blank() +
    geom_line(aes(x = as.numeric(temp)),
                  stat = 'summary', fun = mean) 

Points

geom_point draws points (scatterplot). Typically the stat used is stat_identity as we wish to use the values in two continuous vectors as the coordinates of each point.

The following list describes the mapping aesthetic properties associated with geom_point. The entries in bold are compulsory.
Show attributes
Parameter geom_point
aesthetics
x - variable to map to the x-axis
y - variable to map to the y-axis
group - plot separate series without aesthetic differences
alpha - transparency
colour - colour of the points/lines
fill - inner colour of points/shapes
linetype - type of lines used to construct points/lines
size - thickness of the line
shape - the plotting symbol/character
weight - weightings of values
Feature geom stat position Aesthetic parameters / Notes Example plot
points layer _point _identity identity x,y

geom_point forms the basis of various plots such as scatterplots, maps and others
ggplot(data=df, aes(y = y, x = x)) +
    geom_point()
means points layer _point _identity identity x,y,fun

plots points based on the values provided
ggplot(data=CO2, aes(x = conc, y = uptake)) +
    geom_point()
means points layer _point _summary identity x,y,fun

plots the result of the specified summary function
ggplot(data=CO2, aes(x = conc, y = uptake)) +
    geom_point(stat = "summary", fun = mean)

The plotting symbols are specified by either a number (index of a plotting symbol - see below) or a single character (printed literally).

Text

The following list describes the mapping aesthetic properties associated with geom_text. The entries in bold are compulsory.

Show attributes
Parameter geom_text
- x - variable to map to the x-axis
- y - variable to map to the y-axis
- label - text to use as labels
- group - plot separate series without aesthetic differences
- alpha - transparency
- colour - colour of the points/lines
- fill - inner colour of points/shapes
- linetype - type of lines used to construct points/lines
- shape - symbol shape for points
- size - size of symbol
- family - font family
- fontface - bold, italic, normal etc
- hjust - horizontal justification
- vjust - vertical justification
additional parameters
- parse - whether to parse labels into expressions (to include special characters) FALSE
- nudge_x - horizontal adjustments to label positions 0
- nudge_y - vertical adjustments to label positions 0
- check_overlap - whether to plot text that overlaps other text in layer FALSE
Feature geom stat position Aesthetic parameters / Notes Example plot
Text layer _text _identity identity x,y,label

Text on a plot - useful for depicting the location of observations
ggplot(data=df, aes(y = y, x = x)) +
    geom_text(aes(label = z))
Text layer _text _identity identity x,y,label

Text on a plot - useful for depicting the location of observations
ggplot(data=CO2, aes(y = uptake, x = conc)) +
    geom_text(aes(label = Treatment))
Text layer _text _identity identity x,y,label

Text on a plot - useful for depicting the location of observations
ggplot(data=CO2, aes(y = uptake, x = conc)) +
    geom_text(aes(label = toupper(substr(Treatment, 1, 1))))

Horizontal (hjust) and vertical (vjust) text justification controls are often a source of confusion and this is further exacerbated when combined with angle control. The following excellent demonstration from here provides a visual aid to understanding the use of these controls.

td <- expand.grid(
    hjust=c(0, 0.5, 1),
    vjust=c(0, 0.5, 1),
    angle=c(0, 45, 90),
    text="text"
)

ggplot(td, aes(x=hjust, y=vjust)) + 
    geom_point() +
    geom_text(aes(label=text, angle=angle, hjust=hjust, vjust=vjust)) + 
    facet_grid(~angle) +
    scale_x_continuous(breaks=c(0, 0.5, 1), expand=c(0, 0.2)) +
    scale_y_continuous(breaks=c(0, 0.5, 1), expand=c(0, 0.2))

Paths

geom_path draws paths (line plots). Paths order the coordinates according to the order in the data frame (c.f. geom_line and geom_step)

Show attributes
Parameter geom_path
- x - variable to map to the x-axis
- y - variable to map to the y-axis
- group - plot separate series without aesthetic differences
- alpha - transparency
- colour - colour of the points/lines
- fill - inner colour of points/shapes
- linetype - type of lines used to construct points/lines
- shape - symbol shape for points
- size - size of symbol
additional parameters
- lineend - line end style (round, butt, squate) ‘butt’
- linejoin - line join style (round, mitre, bevel) ‘round’
- linemitre - line mitre limit 10
- arrow - arrow specification (grid::arrow()) NULL
Feature geom stat position Aesthetic parameters / Notes Example plot
paths layer _path _identity identity x,y

geom_path draws lines connecting coordinates in the order present in the data frame
ggplot(data=df, aes(y = y, x = x)) +
    geom_path()

The simple line types available are highlighted in the following figure:

Polygons

geom_polygon draws polygons with the coordinates ordered according to the order in the data frame.

Show attributes
Parameter geom_polygon
- x - variable to map to the x-axis
- y - variable to map to the y-axis
- group - plot separate series without aesthetic differences
- alpha - transparency
- colour - colour of the points/lines
- fill - inner colour of points/shapes
- linetype - type of lines used to construct points/lines
- shape - symbol shape for points
- size - size of symbol
additional parameters
- rule - determines how holes in polygons are treated ‘evenodd’
Feature geom stat position Aesthetic parameters / Notes Example plot
polygon layer _polygon _identity identity x,y

geom_polygon draws polygons using coordinates in the order present in the data frame
ggplot(data=df, aes(y = y, x = x)) +
    geom_polygon()

Areas

geom_area draws areas under curves with the coordinates ordered according to the order in the data frame.

Show attributes
Parameter geom_area
- x - variable to map to the x-axis
- y - variable to map to the y-axis
- group - plot separate series without aesthetic differences
- alpha - transparency
- colour - colour of the points/lines
- fill - inner colour of points/shapes
- linetype - type of lines used to construct points/lines
- shape - symbol shape for points
- size - size of symbol
additional parameters
- outline.type - determines the type of outline to draw around area ‘both’
Feature geom stat position Aesthetic parameters / Notes Example plot
area layer _area _identity identity x,y

geom_area draws areas under a curve using coordinates in the order present in the data frame
ggplot(data=df, aes(y = y, x = x)) +
    geom_area()

Ribbons

geom_ribbon draws ribbons (polygons) based on upper (max) and lower (min) levels of y associated with each level of x and are typically used to represent uncertainty in trends.

Show attributes
Parameter geom_ribbon
- x - variable to map to the x-axis
- y - variable to map to the y-axis
- group - plot separate series without aesthetic differences
- alpha - transparency
- colour - colour of the points/lines
- fill - inner colour of points/shapes
- linetype - type of lines used to construct points/lines
- shape - symbol shape for points
- size - size of symbol
additional parameters
- outline.type - determines the type of outline to draw around area ‘both’
Feature geom stat position Aesthetic parameters / Notes Example plot
ribbon layer _ribbon _identity identity x,y

geom_ribbon draws ribbons on a plot - useful for depicting uncertainty (confidence/credibility) intervals,
ggplot(data=df, aes(ymin = y -1, ymax = y + 1, x = x)) +
    geom_ribbon()
ribbon layer _ribbon _identity identity x,y

geom_ribbon draws ribbons on a plot - useful for depicting uncertainty (confidence/credibility) intervals,
BOD.lm <- lm(demand ~ Time, data = BOD)
newdata <- with(BOD, data.frame(Time = seq(min(Time), max(Time),
                                           length = 100)))
newdata <- newdata %>% cbind(predict(BOD.lm, newdata = newdata,
                                     interval = 'confidence'))
ggplot(data=newdata) +
    geom_ribbon(aes(x = Time, ymin = lwr, ymax = upr))
ribbon layer _ribbon _identity identity x,y

geom_ribbon draws ribbons on a plot - useful for depicting uncertainty (confidence/credibility) intervals,
BOD.lm <- lm(demand ~ Time, data = BOD)
newdata <- with(BOD, data.frame(Time = seq(min(Time), max(Time),
                                           length = 100)))
newdata <- newdata %>% cbind(predict(BOD.lm, newdata = newdata,
                                     interval = 'confidence'))
ggplot(data=newdata, aes(x = Time)) +
    geom_ribbon(aes(x = Time, ymin = lwr, ymax = upr),
                fill='orange') +
    geom_line(aes(y = fit)) +
    geom_point(data = BOD, aes(y=demand))

Visualising distributions

Boxplots

geom_boxplot constructs boxplots. The values of the various elements of the boxplot (quantiles, whiskers etc) are calculated by its main pairing function (stat_boxplot). The following list describes the mapping aesthetic properties associated with geom_boxplot. The entries in bold are compulsory. Note that boxplots are usually specified via the geom_boxplot function which will engage the stat_boxplot to calculate the quantiles, whiskers and outliers. Therefore, confusingly, when calling geom_boxplot, the compulsory parameters are actually those required by stat_boxplot (unless you indicated to use stat_identity).

Show attributes
Parameter geom_boxplot stat_boxplot
aesthetics
x - variable to map to the x-axis
y - variable to map to the other axis
lower - value of the lower box line (25th percentile)
middle - value of the middle box line (50th percentile)
upper - value of the upper box line (75th percentile)
ymin - value of lower whisker
ymax - value of upper whisker
group - plot separate series without aesthetic differences
alpha - transparency
colour - colour of the points/lines
fill - inner colour of points/shapes
linetype - type of lines used to construct points/lines
size - thickness of the line
weight - weightings of values
additional parameters
outlier.colour - color of symbols for outliers NULL NULL
outlier.fill - fill of symbols for outliers NULL NULL
outlier.shape - shape of symbols for outliers NULL NULL
outlier.size - size of symbols for outliers NULL NULL
outlier.stroke - colour of lines in symbols for outliers NULL NULL
outlier.alpha - transparency of symbols for outliers NULL NULL
notch - whether to notch the boxplots FALSE FALSE
notchwidth - width of notch 0.5 0.5
Computed variables
lower - value of the lower box line (25th percentile)
middle - value of the middle box line (50th percentile)
upper - value of the upper box line (75th percentile)
ymin - value of lower whisker
ymax - value of upper whisker
Feature geom stat position Aesthetic parameters / Notes Example plot
boxplot _boxplot _boxplot dodge x

plot of quantiles, whiskers and outliers.
ggplot(data=diamonds, aes(x = carat)) +
    geom_boxplot()
boxplot _boxplot _boxplot dodge y

plot of quantiles, whiskers and outliers.
ggplot(data=diamonds, aes(y = carat)) +
    geom_boxplot()
conditional boxplot _boxplot _boxplot dodge y,x

plot of quantiles, whiskers and outliers.
ggplot(data=diamonds, aes(y = carat, x = cut)) +
    geom_boxplot()

Histograms

geom_histogram draws histograms of continuous data after binning the data,

The following list describes the mapping aesthetic properties associated with geom_histogram. The entries in bold are compulsory.

Show attributes
Parameter geom_histogram stat_bin
aesthetics
x - variable to map to the x-axis
group - plot separate series without aesthetic differences
alpha - transparency
colour - colour of the points/lines
fill - inner colour of points/shapes
linetype - type of lines used to construct points/lines
size - thickness of the line
weight - weightings of values
additional parameters
binwidth - width of the bins NULL NULL
bins - number of bins NULL NULL
breaks - vector of bin boundaries NULL
center - bin position specifier NULL
boundary - bin position specifier NULL
closed - which bin edge is included c(‘right’,‘left’)
pad - whether to include empty bins at either end of x FALSE
orientation - which axis (x or y) to operate on NA NA
Computed variables
count - number of points in bin
density - density of points in bin
ncount - counts scaled to max of 1
ndensity - density scaled to max of 1
Feature geom stat position Aesthetic parameters / Notes Example plot
histogram layer _histogram _bin stack x or y

geom_histogram bins continuous data and uses the number of cases in each bin as the height of a set of rectangles.

Computed variables:
ggplot(data = diamonds, aes(x = carat)) +
    geom_histogram()
histogram layer _histogram _bin stack x or y

the granularity of the histogram can be altered by changing the binwidth.
ggplot(data = diamonds, aes(x = carat)) +
    geom_histogram(binwidth = 0.05)
histogram layer _histogram _bin stack x or y

the granularity of the histogram can be altered by changing the number of bins.
ggplot(data = diamonds, aes(x = carat)) +
    geom_histogram(bins = 10)
histogram layer _histogram _bin stack x or y

geom_histogram bins continuous data and uses the number of cases in each bin as the height of a set of rectangles.

ggplot(data = diamonds, aes(x = carat)) +
    geom_histogram(aes(fill = cut))
histogram layer _histogram _bin dodge x or y

geom_histogram bins continuous data and uses the number of cases in each bin as the height of a set of rectangles.

ggplot(data = diamonds, aes(x = carat)) +
    geom_histogram(aes(fill = cut), position = 'dodge')

Density
plots

geom_density constructs smooth density distributions from continuous vectors. The actual smoothed densities are calculated by its main pairing function (stat_density). The following list describes the mapping aesthetic properties associated with geom_density and stat_density. The entries in bold are compulsory. Note that density plots are usually specified via the geom_density function which will engage the stat_density. Therefore, confusingly, when calling geom_density, the compulsory paramaters are actually those required by stat_density (unless you indicated to use stat_identity).

Show attributes
Parameter geom_density stat_density
aesthetics
x - variable to map to the x-axis
group - plot separate series without aesthetic differences
alpha - transparency
colour - colour of the points/lines
fill - inner colour of points/shapes
linetype - type of lines used to construct points/lines
size - thickness of the line
weight - weightings of values
additional parameters
bw - bandwidth smoothing (either sd of kernel or name of function) “nrd0” “nrd0”
adjust - multiplicate bandwidth adjustment 1 1
kernel - density() kernel to use “gaussian” “gaussian”
n - number of equ-spaced points to estimate density 512 512
trim - whether to trim the range of data FALSE FALSE
orientation - which axis (x or y) to operate on NA NA
Computed variables
density - density of points in bin
count - density * number of points
scaled density - density scaled to max of 1
ndensity - density scaled to max of 1
Feature geom stat position Aesthetic parameters / Notes Example plot
density layer _density _density identity x or y

ggplot(data = diamonds, aes(x = carat)) +
    geom_density()
density layer _density _density identity x or y

ggplot(data = diamonds, aes(x = carat)) +
    geom_density(bw=0.1)
density layer _density _density identity x or y, fill or other grouping

Multiple densities with overlapping ranges
ggplot(data = diamonds, aes(x = carat)) +
    geom_density(aes(fill = cut), alpha=0.5)
density layer _density _density stack x or y, fill or other grouping

Multiple densities stacked on top of one another
ggplot(data = diamonds, aes(x = carat)) +
    geom_density(aes(fill = cut), position = 'stack')

Violin
plots

geom_violin constructs violin plots. Violin plots are a blend on boxplot and density plots in that they are a density plot mirrored across a central axis and displayed similarly to a boxplot. Since they are derived from density plots, geom_violin and its stat (stat_ydensity) have most of the same parameters as geom_density/stat_density. Violin plots are a useful way to present continuous distributions that have greater granularity than boxplots.

Show attributes
Parameter geom_violin stat_ydensity
aesthetics
x - variable to map to the x-axis
group - plot separate series without aesthetic differences
alpha - transparency
colour - colour of the points/lines
fill - inner colour of points/shapes
linetype - type of lines used to construct points/lines
size - thickness of the line
weight - weightings of values
additional parameters
bw - bandwidth smoothing (either sd of kernel or name of function) “nrd0” “nrd0”
adjust - multiplicate bandwidth adjustment 1 1
kernel - density() kernel to use “gaussian” “gaussian”
n - number of equ-spaced points to estimate density 512 512
trim - whether to trim the range of data FALSE FALSE
orientation - which axis (x or y) to operate on NA NA
Computed variables
density - density of points in bin
count - density * number of points
scaled density - density scaled to max of 1
ndensity - density scaled to max of 1
Feature geom stat position Aesthetic parameters / Notes Example plot
violin _violin _ydensity dodge x

plot of quantiles, whiskers and outliers.
ggplot(diamonds) +
    geom_violin(aes(y = carat, x = carat), orientation = 'x')
violin _violin _ydensity dodge y

plot of quantiles, whiskers and outliers.
ggplot(diamonds) +
    geom_violin(aes(y = carat, x = carat), orientation = 'y')
conditional violin _violin _ydensity dodge y,x

plot of quantiles, whiskers and outliers.
ggplot(diamonds) +
    geom_violin(aes(y = carat, x = cut))

QQ
plots

geom_qq constructs quantile-quantile (QQ) plots. QQ plots illustrate the quantiles of the sample distribution against the quantiles expected for the theoretical distribution. A straight line implies that the sample distribution matches the theoretical distribution well. Deviations (typically at the tails) imply a lack of match. To help assess deviations from linearity, the geom_qq_line/stat_qq_line function depicts the ideal match as a straight line for comparison.

Show attributes
Parameter geom_qq stat_qq
aesthetics
sample - variable to map to the x-axis
group - plot separate series without aesthetic differences
alpha - transparency
colour - colour of the points/lines
fill - inner colour of points/shapes
linetype - type of lines used to construct points/lines
size - thickness of the line
weight - weightings of values
additional parameters
distribution - function that calculates quantiles for a distribution stats::qnorm stats::qnorm
dparams - additional parameters for the distribution list() list()
orientation - which axis (x or y) to operate on NA NA
Computed variables
sample - sample quantiles
theoretical - theoretical quantiles
Feature geom stat position Aesthetic parameters / Notes Example plot
QQ plot _qq _qq identity sample

ggplot(diamonds, aes(sample = carat)) +
    geom_qq() +
    geom_qq_line()
QQ plot _qq _qq identity sample

this example will explore a Gamma theoretical distribution (rather than the default Gaussian). When specifying an alternative distribution, it may be necessary to supply certain distribution parameters. In this case, the appropriate shape parameter for the Gamma distribution is required. This is first estimated via the fitdistr() function from the MASS _package`.
shape <- MASS::fitdistr(diamonds$carat,
                        densfun = "gamma")$estimate["shape"]
ggplot(diamonds, aes(sample = carat)) +
    geom_qq(distribution = stats::qgamma,
            dparams = list(shape = shape)) +
    geom_qq_line(distribution = stats::qgamma,
                 dparams = list(shape = shape))
QQ plot _qq _qq identity sample

ggplot(diamonds, aes(sample = carat, colour = cut)) +
    geom_qq() +
    geom_qq_line()

Bar
plots

geom_bar constructs barcharts. By default, the bins of each bar along with the associated bar heights are calculated by the stats_count function. The following list describes the mapping aesthetic properties associated with geom_bar and stats_count. The entries in bold are compulsory.

Show attributes
Parameter geom_bar stat_count
aesthetics
x or y - variable to map to the x/y-axis
group - plot separate series without aesthetic differences
alpha - transparency
colour - colour of the points/lines
fill - inner colour of points/shapes
linetype - type of lines used to construct points/lines
size - thickness of the line
weight - weightings of values
additional parameters
width - width of the bars NULL NULL
orientation - which axis (x or y) to operate on NA NA
Computed variables
count - number of points to bin
prop - groupwise proportion
Feature geom stat position Aesthetic parameters / Notes Example plot
Bar plot _bar _count stack sample

ggplot(diamonds, aes(x = cut)) +
    geom_bar()
Stacked bar plot _bar _count stack sample

by default a viridis colour blind safe palette is applied.
ggplot(diamonds, aes(x = cut, fill = clarity)) +
    geom_bar()
Conditional bar plot _bar _count dodge2 sample

by default a viridis colour blind safe palette is applied.
ggplot(diamonds, aes(x = cut, fill = clarity)) +
    geom_bar(position = "dodge2")

Dot
plots

geom_dotplot draws dotplots of continuous data after binning the data. This geom is unusual in that it does not have an associated stat. Instead, it calls its own density function. Dotplots are really only useful for small datasets. The reason for this is that the counts in each bin are represented by circles (the size of which is determined by the bin width) and thus if the counts are high, the stack of circles will extend beyond the y-axis (unless the stack ratio is altered). Moreover, the y-axis scale is meaningless.

The following list describes the mapping aesthetic properties associated with geom_dotplot. The entries in bold are compulsory.

Show attributes
Parameter geom_histogram
aesthetics
x - variable to map to the x-axis
group - plot separate series without aesthetic differences
alpha - transparency
colour - colour of the points/lines
fill - inner colour of points/shapes
linetype - type of lines used to construct points/lines
size - thickness of the line
weight - weightings of values
additional parameters
binwidth - (maximum) bin width NULL
binaxis - the axis to bin along “x”
method - method for binning “dotdensity”
binpositions - method for determining the position of dots “bygroup”
stackdir - which direction to stack dots “up”
stackratio - how close to stack dots 1
dotsize - diameter of dot relative to binwidth 1
stackgroups - whether to stack dots across groups FALSE
origin - origin of first bin NULL
right - should bin intervals be closed on the right (a, b] or not [a, b) TRUE
width - when binaxis is “y”, the spacing of dot stacks for dodging 0.9
drop - whether to remove bins with zero counts FALSE
Computed variables
count - number of points in bin
density - density of points in bin
ncount - counts scaled to max of 1
ndensity - density scaled to max of 1
Feature geom stat position Aesthetic parameters / Notes Example plot
dotplot layer _dotplot identity x or y

ggplot(data = CO2, aes(x = uptake)) +
    geom_dotplot()
dotplot layer _dotplot identity x or y

ggplot(data = CO2, aes(x = uptake)) +
    geom_dotplot(binwidth = 3)
dotplot layer _dotplot identity x or y

ggplot(data = CO2, aes(x = uptake, fill = Type)) +
    geom_dotplot(stackgroups = TRUE,
                 binpositions = 'all',
                 binwidth=3, dotsize=1) 

Scatterplot
matrix

The ggpairs() function is not actually part of the ggplot2 package. Rather it is part of its own package (GGally). Nevertheless, this graphic, in which all pairs of variables are plotted in a matrix of panels can be a very useful way to explore the individual and relational characteristics of multiple variables simultaneously.

Show attributes
Parameter geom_histogram
aesthetics
group - plot separate series without aesthetic differences
alpha - transparency
colour - colour of the points/lines
fill - inner colour of points/shapes
linetype - type of lines used to construct points/lines
size - thickness of the line
weight - weightings of values
additional parameters
columns - which columns to include 1:ncol(data)
title,xlab,ylab - titles NULL
upper,lower - functions for plots to appear in off diagonal panels
diag - function for plots to appear in diagonal panels
axisLabels - whether and how to display axis labels c(“show”, “internal”, “none”)
columnLabels - label names to display colnames(data[columns])
labeller - facet labeller function “label_value”
switch - which (if any) facet labels to switch position NULL
showStrips - whether to display all strips (panel banners) NULL
legend - whether or position of legend NULL
cardinality_threshold - max number of factor levels permitted 15
progress - whether to show a progress bar while computing (if >15 panels) NULL
proportions - amount of area given to each plot NULL
Feature geom stat position Aesthetic parameters / Notes Example plot
dotplot layer _dotplot identity x or y

ggpairs(iris, colour = "Species", upper = list(continuous = "density",
    combo = "box"), diag = list(continuous = "density"),
    lower = list(continuous = "smooth"), axisLabels = "show")

Visualising uncertainty

Error
bars

geom_errorbar draws error bars based on upper and lower levels of y associated with each level of x.

Show attributes
Parameter geom_errorbar
aesthetics
x - variable to map to the x-axis
y - variable to map to the y axis
group - plot separate series without aesthetic differences
alpha - transparency
colour - colour of the points/lines
fill - inner colour of points/shapes
linetype - type of lines used to construct points/lines
size - thickness of the line
weight - weightings of values
additional parameters
width - width of the caps on the bars 1
Computed variables
Feature geom stat position Aesthetic parameters / Notes Example plot
error bars _errorbar _identity identity x,y

warpbreaks.sum <- warpbreaks %>%
    group_by(wool) %>%
    summarise(mean_se(breaks))
ggplot(warpbreaks.sum, aes(y = y, x = wool, ymin = ymin, ymax = ymax)) +
    geom_errorbar() 
error bars _errorbar _identity identity x,y

warpbreaks.sum <- warpbreaks %>%
    group_by(wool) %>%
    summarise(mean_se(breaks))
ggplot(warpbreaks.sum, aes(y = y, x = wool, ymin = ymin, ymax = ymax)) +
    geom_errorbar(width = 0.25) 
error bars _errorbar _identity identity x,y

warpbreaks.sum <- warpbreaks %>%
    group_by(wool) %>%
    summarise(mean_se(breaks))
ggplot(warpbreaks.sum, aes(y = y, x = wool, ymin = ymin, ymax = ymax)) +
    geom_crossbar(width = 0.25) 
error bars _errorbar _identity identity x,y

warpbreaks.sum <- warpbreaks %>%
    group_by(wool, tension) %>%
    summarise(mean_se(breaks))
ggplot(warpbreaks.sum, aes(y = y, x = tension, ymin = ymin, ymax = ymax)) +
    geom_errorbar(aes(colour = wool),
                  position = position_dodge(width = 0.5),
                  width = 0.25) 

Line
ranges

geom_lineranges draws uncertainty bars based on upper and lower levels of y associated with each level of x.

Show attributes
Parameter geom_linerange
aesthetics
x - variable to map to the x-axis
y - variable to map to the y axis
group - plot separate series without aesthetic differences
alpha - transparency
colour - colour of the points/lines
fill - inner colour of points/shapes
linetype - type of lines used to construct points/lines
size - thickness of the line
weight - weightings of values
additional parameters
Computed variables
Feature geom stat position Aesthetic parameters / Notes Example plot
line range _linerange _identity identity x,y

warpbreaks.sum <- warpbreaks %>%
    group_by(wool) %>%
    summarise(mean_se(breaks))
ggplot(warpbreaks.sum, aes(y = y, x = wool, ymin = ymin, ymax = ymax)) +
    geom_linerange() 
line ranges _lineranges _identity identity x,y

warpbreaks.sum <- warpbreaks %>%
    group_by(wool, tension) %>%
    summarise(mean_se(breaks))
ggplot(warpbreaks.sum, aes(y = y, x = tension, ymin = ymin, ymax = ymax)) +
    geom_linerange(aes(colour = wool),
                  position = position_dodge(width = 0.5)) 

Point
ranges

geom_lineranges draws uncertainty bars based on upper and lower levels of y associated with each level of x.

Show attributes
Parameter geom_pointrange
aesthetics
x - variable to map to the x-axis
y - variable to map to the y axis
group - plot separate series without aesthetic differences
alpha - transparency
colour - colour of the points/lines
fill - inner colour of points/shapes
linetype - type of lines used to construct points/lines
size - thickness of the line
weight - weightings of values
additional parameters
flatten - a multiplicative factor to increase the point size 1
Computed variables
Feature geom stat position Aesthetic parameters / Notes Example plot
point range _pointrange _identity identity x,y

warpbreaks.sum <- warpbreaks %>%
    group_by(wool) %>%
    summarise(mean_se(breaks))
ggplot(warpbreaks.sum, aes(y = y, x = wool, ymin = ymin, ymax = ymax)) +
    geom_pointrange() 
point ranges _pointranges _identity identity x,y

warpbreaks.sum <- warpbreaks %>%
    group_by(wool) %>%
    summarise(mean_se(breaks))
ggplot(warpbreaks.sum, aes(y = y, x = wool, ymin = ymin, ymax = ymax)) +
    geom_pointrange(fatten = 5) 
point ranges _pointranges _identity identity x,y

warpbreaks.sum <- warpbreaks %>%
    group_by(wool, tension) %>%
    summarise(mean_se(breaks))
ggplot(warpbreaks.sum, aes(y = y, x = tension, ymin = ymin, ymax = ymax)) +
    geom_pointrange(aes(colour = wool),
                  position = position_dodge(width = 0.5)) 

Ribbons

geom_ribbon draws uncertainty envelopes based on upper and lower levels of y associated with each level of x.

see ribbons

Other features

Straight
lines

geom_vline and geom_hline draw vertical and horizontal lines respectively. These are particularly useful for:

  • marking cross-hairs in ordination plots
  • providing extended guides along either axes.

geom_abline is used for adding linear regression lines in the form of y = bx + a where b is the slope and a is the intercept (this is where the ab in abline comes from).

Show attributes
Parameter geom_vline geom_hline geom_abline
aesthetics
xintercept - x-axis coordinate crossed by vline
yintercept - y-axis coordinate crossed by hline
intercept - y-axis coordinate crossed by abline
slope - slope (gradient) of abline
group - plot separate series without aesthetic differences
alpha - transparency
colour - colour of the points/lines
fill - inner colour of points/shapes
linetype - type of lines used to construct points/lines
size - thickness of the line
weight - weightings of values
additional parameters
Computed variables
Feature geom stat position Aesthetic parameters / Notes Example plot
straight lines _vline _identity identity x,y

ggplot(filter(CO2, Plant == first(Plant))) +
    geom_vline(xintercept = 500, linetype = 'dashed') +
    geom_point(aes(x = conc, y = uptake)) 
straight lines _hline _identity identity x,y

ggplot(filter(CO2, Plant == first(Plant))) +
    geom_hline(yintercept = 25, linetype = 'dashed') +
    geom_point(aes(x = conc, y = uptake)) 
straight lines _abline _identity identity x,y

ggplot(filter(CO2, Plant == first(Plant))) +
    geom_abline(slope = 0.01, intercept = 30, linetype = 'dashed') +
    geom_point(aes(x = conc, y = uptake)) 

Segments

geom_segment draws segments (separate lines) joining pairs of coordinates. These can be useful to represent vectors (e.g. wind speed and direction on a map) or movement, differences etc (particularly if given an arrow head).

Show attributes
Parameter geom_segment
aesthetics
x - x-axis coordinates for the start of lines
y - y-axis coordinates for the start of lines
xend - x-axis coordinates for the end of lines
yend - y-axis coordinates for the end of lines
group - plot separate series without aesthetic differences
alpha - transparency
colour - colour of the points/lines
fill - inner colour of points/shapes
linetype - type of lines used to construct points/lines
size - thickness of the line
weight - weightings of values
additional parameters
arrow - specification of arrow heads NULL
arrow.fill - fill colour of arrow head NULL
lineend - style of line end “butt”
linejoin - style of line join “round”
Computed variables
Feature geom stat position Aesthetic parameters / Notes Example plot
line segements _segement _identity identity x,y

BOD.lm <- lm(demand ~ Time, data = BOD)
BOD$fitted <- fitted(BOD.lm)
BOD$resid <- resid(BOD.lm)
ggplot(BOD)+
    geom_segment(aes(x=Time,y=demand, xend=Time,yend=fitted),
                 arrow = arrow(length=unit(0.5, "cm"), ends = "first")) 

Text

see text

Coordinate system

The coordinate system controls the nature and scale of the axes.

Types of coordinate systems

Cartesian
coordinates

Show attributes
Parameter geom_segment
xlim - limits for the x axis NULL
ylim - limits for the y axis NULL
expand - whether to add a small expansion to the axes to ensure geoms and axes do not overlapp TRUE
expand - whether or not to provide a warning when the default coordinate system is being replaced FALSE
clip - whether or not to clip plotting to within the plotting margins (“on”) or to extend into the margins “on”
Feature coord Notes Example plot
Cartesian coordinates _cartesian

ggplot(data = BOD, aes(x = Time, y = demand)) +
    geom_line() +
    coord_cartesian()

Polar
coordinates

Show attributes
Parameter geom_segment
theta - map angle to either ‘x’ or ‘y’ ‘x’
start - offset (applied clockwise by default) from 12 o’clock in radians 0
direction - which direction (‘clockwise’: 1 or ‘anticlockwise’: -1) 1
clip - whether or not to clip plotting to within the plotting margins (“on”) or to extend into the margins “on”
Feature coord Notes Example plot
Polar coordinates _polar

ggplot(data = BOD, aes(x = Time, y = demand)) +
    geom_line() +
    coord_polar()

Flip
coordinates

Show attributes
Parameter geom_segment
xlim - limits for the x axis NULL
ylim - limits for the y axis NULL
expand - whether to add a small expansion to the axes to ensure geoms and axes do not overlapp TRUE
expand - whether or not to provide a warning when the default coordinate system is being replaced FALSE
clip - whether or not to clip plotting to within the plotting margins (“on”) or to extend into the margins “on”
Feature coord Notes Example plot
Flip coordinates _flip

ggplot(data = BOD, aes(x = Time, y = demand)) +
    geom_line() +
    coord_flip()

Fixed
coordinates

Show attributes
Parameter geom_segment
ratio - aspect ratio (y/x) 1
xlim - limits for the x axis NULL
ylim - limits for the y axis NULL
expand - whether to add a small expansion to the axes to ensure geoms and axes do not overlapp TRUE
expand - whether or not to provide a warning when the default coordinate system is being replaced FALSE
clip - whether or not to clip plotting to within the plotting margins (“on”) or to extend into the margins “on”
Feature coord Notes Example plot
Fixed coordinates _fixed

ggplot(data = BOD, aes(x = Time, y = demand)) +
    geom_line() +
    coord_fixed()
Fixed ratio of coordinates _fixed

ggplot(data = BOD, aes(x = Time, y = demand)) +
    geom_line() +
    coord_fixed(ratio = 0.5)

Transformed
coordinates

Show attributes
Parameter geom_segment
x - the transformation to apply to the x-axis “identity”
y - the transformation to apply to the y-axis “identity”
xlim - limits for the x axis NULL
ylim - limits for the y axis NULL
expand - whether or not to provide a warning when the default coordinate system is being replaced FALSE
clip - whether or not to clip plotting to within the plotting margins (“on”) or to extend into the margins “on”
Feature coord Notes Example plot
Transformed coordinates _trans

ggplot(data = BOD, aes(x = Time, y = demand)) +
    geom_line() +
    coord_trans(x = "log10")
Trans ratio of coordinates _trans

ggplot(data = BOD, aes(x = Time, y = demand)) +
    geom_line() +
    coord_trans(x = scales::exp_trans(2))

Altering axes scales via the coordinate system

Zooming

Modifying scales with coords_ affects the zoom on the graph. That is, it defines the extent and nature of the axes coordinates. By contrast, altering limits via scale_ routines will alter the scope of data included in a manner analogous to operating on a subset of the data.

To illustrate this, lets produce a linear smoother for the BOD data. To help us appreciate the differences between coords_ and scale_ when altering one axis (x in this case), we will ensure that all each plot has the same range of the other axis (y) and that the aspect ratio for the axes are all the same.

g <- ggplot(data = BOD, aes(x = Time, y = demand)) +
    geom_smooth(method = "lm") +
    geom_point()
Show default plot
g + coord_fixed(ratio = 0.1, ylim = c(-5, 35))

Scale via coords scale

g + coord_fixed(ratio = 0.1,
                ylim = c(-5, 35),
                xlim = c(2, 6))

Scale via scale scale

g + coord_fixed(ratio = 0.1,
                ylim = c(-5, 35)) +
    scale_x_continuous(limits = c(2, 6))

Notice that the left hand figure (that restricts the x-axis scale) simply zooms in on the plot thereby cutting some of the data off. By contrast, scale_ (right hand figure) removes data that are outside the range and thus also alters the output of the smoother (linear model).

Geom re-scaling

In addition to altering the zoom of the axes, axes (coordinate system) scales can be transformed to other scales via the coord_trans function. Such transformations of the coordinate system take place after statistics have been calculated and geoms derived. Therefore the shape of geoms are altered.

To illustrate the difference between coord_trans and scale_, lets create a fabricated data set of 50 points in which y is an exponential function of x (with noise).

set.seed(1)
n<-50
dat <- data.frame(x = exp((1:n+rnorm(n,sd=2))/10), y = 1:n+rnorm(n,sd=2))

g <- ggplot(data = dat, aes(x = x, y = y))
Linear scales coord_trans scales_

g + geom_point()

g + geom_point() +
    coord_trans(x="log10")

g + geom_point() +
    scale_x_continuous(trans="log10")

g + geom_point() +
    geom_smooth(method="lm")

g + geom_point() +
    geom_smooth(method="lm") +
    coord_trans(x="log10") 

g + geom_point() +
    geom_smooth(method="lm") +
    scale_x_continuous(trans="log10") 

In the above, the log10 transformer function was applied to either the coordinates or the axes scales. More information about this and other transformer functions is provided in the scales section.

Scales

The idea of scales is that you present the plotting engine with data or characteristics in one scale and use the various scale_ functions to convert those data into another scale. In the grammar of graphics, scales are synonymous for units of data, colors, shapes, sizes etc of plotting features and the axes and guides (legends) provide a visual cue for what the scales are. For example:

  • you might include data that ranges from 10 to 20 units, yet you wish to produce a plot that uses a restricted range of 12-16.
  • you have presented grouped data (data with multiple trends) and instructed the graphing engine to assign different colour codes to each trend. You can then define a colour scale to adjust the exact colours rendered.
  • similarly, you might have indicated how plotting symbol shape and size are to be distinguished in your data set. You can then assign scales that define the exact shapes and symbol sizes rendered.

Technically, scales determine how attributes of the data are mapped into aesthetic geom properties. The majority of geom’s (geometric objects) have the following aesthetic properties:

Parameter
x - the x position (coordinates) of the geom
y - the y position (coordinates) of the geom
size - size of the geom (e.g. the size of points, thickness of lines)
shape - the shape of the geom
linetype - the type of line to use for the geom’s outline (solid, dashed, etc)
colour - the colour of the geom’s outline
fill - the colour of the geom’s fill (inside colour)
alpha - the transparency of the geom (0 = transparent, through to 1 = opaque)

In turn, each of these properties are mapped to a scale - the defaults of which are automatically selected according to what is appropriate for the sort of data. For example, if the variable mapped to an axis is continuous, the a continuous scale is the default. If the variable mapped to an axis is categorical, then a discrete scale is the default. And so on…

The following table describes the typical scale associated with each of the major variable types:

Variable type Scale
numeric - continuous data _continuous - data mapped onto a continuous scale
numeric - continuous data _log10 - data mapped onto a log (base 10) continuous scale
numeric - continuous data _sqrt - data mapped onto a sqrt continuous scale
numeric - continuous data _reverse - data mapped onto a reverse continuous scale
numeric - continuous data _binned - data mapped onto a binned (discretized) scale
factor - categorical data _discrete - data mapped onto a categorical scale
date - date data _date - data mapped according to dates
POSIXct - date/time data _datetime - data mapped according to date/time
POSIXct - date/time data _time - data mapped according to date/time

Some properties, such as colour also have additional scales that are specific to the characteristic. The scales effect not only the characteristics of the geoms, they also effect the guides (legends) that accompany the geoms.

Scaling functions comprise the prefix scale_, followed by the name of an aesthetic property and suffixed by the type of scale. Hence a function to manually define a colour scale would be scale_colour_manual.

  • name - a title applied to the scale. In the case of scales for x and y (the x,y coordinate of geoms), the name is the axis title. For all other scales, the name is the title of the guide (legend).

    Explore

    Feature

    Notes

    Example plot

    Simple axis title

    Provide a more meaningful axis title for the x-axis

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point() +
        scale_x_continuous(name = "CO₂ concentration") 

    Math in axis title

    More elaborate titles that include special characters and mathematical notations are supported via expression()’s. For more info on plotting mathematical expressions, run demo(plotmath).

    Note the use of the ~ character everywhere that a space would appear. That is because an expression cannot have spaces.

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point() +
        scale_x_continuous(
            name = expression(Ambient~CO[2]~concentration~(mg/l))
        ) 

    Math in axis title

    Alternatively, expressions can be built up by pasting objects together.

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point() +
        scale_x_continuous(
            name = expression(paste("Ambient ", CO[2],
                                    " concentration (mg/l)"))) 
  • breaks - the increments on the guide. For scale_x_ and scale_y_, breaks are the axis tick locations. For all other scales, the breaks indicate the increments of the characteristic in the legend (e.g. how many point shapes are featured in the legend).

    Explore

    By default, pretty breaks will be used for continuous (including dates) data. It is possible to define your own breaks.

    Feature

    Notes

    Example plot

    User defined breaks

    Provide a vector of breaks (tick marks)

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point() +
        scale_x_continuous(breaks = c(200, 500, 800)) 

    User defined breaks

    Provide a more useful breaks for log scale axes

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point() +
        scale_x_log10(breaks = as.vector(c(1,2,5,10) %o% 10^(-1:2)))

    User defined breaks

    Alternatively, you can apply other functions that define breaks. There are some useful break functions in the scales package

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point() +
        scale_x_continuous(breaks = scales::breaks_log(n=7))

    User defined breaks

    For discrete data, breaks should return a vector of values that correspond to categorical levels (in the order of the levels). In the following example, only one of the Treatment groups has a tick mark.

    ggplot(data = CO2, aes(x = Treatment, y = uptake)) +
        geom_point() +
        scale_x_discrete(breaks = c("chilled"))
  • labels - the labels given to the increments on the guide. For scale_x_ and scale_y_, labels are the axis tick labels. For all other scales, the labels are the labels given to items in the legend.

    Explore

    The scales package has a number of label formatting functions. These all start with label_

    Feature

    Notes

    Example plot

    User defined tick labels

    Format x-axis tick labels to include comma’s every multiple of 1000

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point() +
        scale_x_continuous(labels = scales::label_comma()) 

    User defined tick labels

    Format y-axis labels to include percentage sign. By default, the label_percent function also assumes that the data mapped to the scale are proportions (that is the values are between 0 and 1). So by default, the function will multiple (scale) the values by 100. In this case, since the y-axis values are all between 0 and 100, we indicate that they should be multiplied by 1 (e.g. no change).

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point() +
        scale_y_continuous(labels = scales::label_percent(scale=1)) 

    User defined tick labels

    Format y-axis labels to include percentage sign. On this occasion we will derive a new variable to map to the y-axis. These values are in the range from 0 to 1, so we do want to scale (multiply) by 100. We will also adjust the accuracy (number to round to). In this case, we will indicate that it should round to the nearest 1 (whole number).

    CO2 <- CO2 %>% mutate(percent = uptake/100)
    ggplot(data = CO2, aes(x = conc, y = percent)) +
        geom_point() +
        scale_y_continuous(labels = scales::label_percent(accuracy = 1)) 

    User defined tick labels

    Format the x-axis ticks to append ‘.spp’ after each Type and make each tick mark italic. To apply any mathematical notation (including italic formatting) we must use a label formatter that parses expressions. We will define the format of the labels first in the dataset.

    CO2 <- CO2 %>% mutate(species = paste0('italic(', Type, '.spp)'))
    ggplot(data = CO2, aes(x = species, y = uptake)) +
        geom_point() +
        scale_x_discrete(labels = scales::label_parse()) 

    User defined tick labels

    Or, we can define the formatting on the fly,

    ggplot(data = CO2, aes(x = Type, y = uptake)) +
        geom_point() +
        scale_x_discrete(
            labels = scales::label_math(italic(paste(.x, '.spp', sep='')))
        )
  • limits - the span/range of data represented in the scale. Note, if the range is inside the range of the data, the data are sub-setted.

    Explore

    Feature

    Notes

    Example plot

    Range of the scale

    Extend the range of the x-axis

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point() +
        scale_x_continuous(limits = c(0, 2000)) 

    Range of the scale

    Extend the range represented by a colour bar

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point(aes(colour=uptake)) +
        scale_colour_continuous(limits = c(0,60)) 

    Range of the scale

    This can also include categorical data - in this case, we are adding an additional category. Although this category does not appear in the data, it may appear in other data for which you are producing similar plots and you wish to maintain the same legends and colour palettes.

    ggplot(data = CO2, aes(x = Type, y = uptake)) +
        geom_violin(aes(fill=Treatment)) +
        scale_fill_discrete(limits = c('nonchilled','chilled','heated')) 
  • trans - scale transformations applied - obviously this is only relevant to scales that are associated with continuous data.

    Explore

    Feature

    Notes

    Example plot

    Log (base 10) scale

    Apply a log (base 10) transformation of the x-axis

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point() +
        scale_x_continuous(trans = "log10") 

    Square-root scale

    Apply a square-root transformation of the x-axis

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point() +
        scale_x_continuous(trans = "sqrt") 

    Log (base 2) scale

    Apply a log (base 2) transformation of the x-axis The scales package has a set of functions to achieve common transformation.

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point() +
        scale_x_continuous(trans = scales::log10_trans()) 

    Log (base 2) scale

    There is also a general log transform that allows you to indicate the logarithmic base. When using the log_trans function, it is a good idea to also use a related function to control the position of tick mark breaks.

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point() +
        scale_x_continuous(trans = scales::log_trans(base = 2),
                           breaks = scales::log_breaks(base = 2)) 

    Log (base 2) scale

    If you wish to apply a logarithmic scale transform, yet also include a tickmark at 0, then the psuedo_log_trans is a very useful function.

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point() +
        scale_x_continuous(trans = scales::pseudo_log_trans(),
                           limits = c(0, 1500)) 
  • guide - a function used to create/modify the associated guide (axes or legend).

    Explore

    Feature

    Notes

    Example plot

    Remove guide

    Scale the size of the points according to a continuous variable, yet remove the associated legend.

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point(aes(size = uptake)) +
        scale_size(guide = NULL)

    Override aethetics

    Colour the points according to a categorical variable (Type), but increase the size of the points in the legend to make them more obvious.

    ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point(aes(colour = Type)) +
        scale_colour_discrete(
            guide = guide_legend(override.aes = list(size = 5))
        )

Axes

Show attributes
Parameter
All
position - axis position (‘left’, ‘right, ’top’, ‘bottom’)
sec.axis - secondary axis
_date, _datetime
date_breaks - distance between breaks (in date units)
date_labels - formatting for labels
date_minor_breaks - distance between minor breaks (in date units)
timezone - timezeone to use when displaying date/datetime
Feature scale Notes Example plot
Linear scaling _continuous

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point() +
    scale_x_continuous()
Add a secondary y-axis _continuous

Add a secondary y-axis and alter its scale. Note, by design, ggplot only permits secondary axes that are derived from the primary axis (are pure re-scale) - it is not possible (without unsupported effort) to represent an additional variable.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point() +
    scale_y_continuous(
        name = expression(Uptake~(mu*mol/m^3)),
        sec.axis = sec_axis(
            name = expression(Uptake~(mg/m^3)),
            trans = ~ .*44/1000)
    )
Add a secondary y-axis _continuous Add a secondary y-axis, except put the derived axis on the left side and the standard axis on the right
ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point() +
    scale_y_continuous(
        name = expression(Uptake~(mu*mol/m^3)),
        position = "right",
        sec.axis = sec_axis(
            name = expression(Uptake~(mg/m^3)),
            trans = ~ .*44/1000)
    )

Size

The scale_size_ scales control the size of geoms (such as the size of points).

Show attributes
Parameter _size _size_area _size_binned
range - range (min, max) of symbol sizes c(1, 6) c(1,6)
max_size - maximum size of symbols 6
n.breaks - approximate number of major breaks NULL
nice.breaks - whether to use nice breaks TRUE
Feature scale Notes Example plot
Scale size _size Scale the size according to a continuous variable. The size of the symbols will be proportional to the value in the variable and the guide (legend) will provide an indication of the symbol sizes correspondingto a set of values.
ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(size = uptake)) +
    scale_size()
Scale size _size Scale the size according to a continuous variable
ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(size = uptake)) +
    scale_size(range = c(0.5,3))
Scale size _size_binned Scale the size according to a continuous variable that has been binned. In this case, as there are five bins, the symbols will be of one of five sizes (rather than a continuum).
ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(size = uptake)) +
    scale_size_binned()
Scale size _size_discrete Scale the size according to the levels of a categorical variable
ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(size = Type)) +
    scale_size_discrete()

Shape

The scale_shape_ scales control the shape of geoms (such as the shape of the plotting point)

Show attributes
Parameter _shape _shape_binned
solid - whether the plotting symbols should be solid (TRUE) or hollow TRUE TRUE
Feature scale Notes Example plot
Scale shape _shape

Use hollow shapes.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(shape = Type)) +
    scale_shape(solid = FALSE)
Scale shape _shape_manual

Manually defined the symbol shapes.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(shape = Type)) +
    scale_shape_manual(values = c(16, 21))

Linetype

The scale_linetype_ scales control the linetype of geoms.

Feature scale Notes Example plot
Scale line type _linetype

Manually define the line types and alter the associated legend labels.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_smooth(aes(linetype = Treatment)) +
    scale_linetype_manual(name = "Temperature",
                       values = c('solid', 'dotted'),
                       labels = c('Chilled', 'Non-chilled'))
Scale line type _linetype

Manually define the line types and alter the associated legend labels and remove the ribbon from the legend.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_smooth(aes(linetype = Treatment)) +
    scale_linetype_manual(name = "Temperature",
                       values = c('solid', 'dotted'),
                       labels = c('Chilled', 'Non-chilled'),
                       guide = guide_legend(override.aes = list(fill = NA))
                       )

Colour
fill

Colour (or color) is used to represent the colour of lines and solid symbols (e.g. the outer color of shapes). By contrast, fill is used to represent the filling (inner) colour of shapes.

Colors can be specified by either:

  • a name of one of the 657 named colors

    Color names

    The names of all the available colors can be obtained via:

    colors()

    Below is a visual representation of those colours and their names (although you are going to need exceptional eye sight to read the names ;)).

  • hexedecimal codes (e.g. #FF0000 is ‘red’). This can also be an eight digit code in which case the last two digits represent alpha (e.g. #FF000050 is 50% transparent red).

  • RGB color codes

  • a colour palette

    Palettes

    colorspace::hcl_palettes(plot = TRUE, n = 5)

    RColorBrewer::display.brewer.all()

Show attributes
Parameter default default
_continuous _binned
type - the type of colour scale ‘gradient’
(‘gradient’, ‘viridis’)
_gradient gradient2
low - colour of low end of gradient ‘#132B43’ muted(“red”)
high - colour of high end of gradient ‘#56B1F7’ muted(“blue”
space - colour space ‘Lab’ ‘Lab’
mid - colour of mid point in gradient ‘white’
midpoint - data value associated with middle of gradient 0
_gradientn
colours - vector of colours
values - position associated with eaah colour
_brewer _distiller
type - type of color scale (‘div’, ‘seq’ or ‘qual’) ‘seq’ ‘seq’
palette - name or number of colorbrewer palette 1 1
direction - order of colours from the palette 1 -1
Feature scale Notes Example plot
Scale colour type _colour_gradient

Manually define a colour scale that gradually transitions from red to blue.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(colour = uptake)) +
    scale_colour_gradient(low = 'red', high = 'blue')
Scale colour type _colour_gradient2

Manually define a colour scale that gradually transitions from red to blue via a white middle.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(colour = uptake)) +
    scale_colour_gradient2(low = 'red', mid = "white", high = 'blue',
                           midpoint = 25)
Scale colour type _colour_gradientn

Manually define a colour scale that gradually transitions along a pre-defined colour palette.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(colour = uptake)) +
    scale_colour_gradientn(colours = terrain.colors(12))
Scale colour type _colour_distiller

Manually define a colour scale that gradually transitions according to a colorbrewer palette on a continuous variable.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(colour = uptake)) +
    scale_colour_distiller(palette = 'Reds')
Scale colour type _color_viridis_c

Manually define a colour scale that gradually transitions according to a Viridis colourblind safe palette.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(colour = uptake)) +
    scale_color_viridis_c(option = "D")
Scale colour type _color_brewer

Manually define a colour scale that uses the ‘Divergent’ (div) RdYlGr(palette 2) colorBrewer palette on a categorical variable.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(colour = interaction(Treatment, Type))) +
    scale_color_brewer(type = 'div', palette = 2)
Scale colour type _color_distiller

Apply an interpolated colorbrewer scale ‘Oranges’ sequential scale (reverse order).

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(colour = uptake)) +
    scale_color_distiller(type = 'seq', palette = 'Oranges', direction = -1)
Scale colour type _color_fermenter

Apply an interpolated colorbrewer scale ‘Oranges’ sequential scale (reverse order) and binned.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(colour = uptake)) +
    scale_color_fermenter(type = 'seq', palette = 'Oranges', direction = -1)
Scale colour type _color_gradientn

Apply a user-defined color palette

my_palette = colorRampPalette(colors=c('red','green','blue'))
ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(colour = uptake)) +
    scale_color_gradientn(colours = my_palette(5))
Scale colour type _color_hue

Apply a hue palette to categorical data.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(colour = interaction(Treatment, Type))) +
    scale_color_hue(l=80, c=130)
Scale colour type _colour_grey

Apply a hue palette to categorical data.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(colour = interaction(Treatment, Type))) +
    scale_colour_grey(start = 0.2, end = 0.8)
Scale colour type _colour_manual

Manually set the colours for a categorical variable. One of the colours is a named colour, the other is a hex code.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(colour = Type)) +
    scale_colour_manual(breaks = c('Mississippi','Quebec'),
                        values = c('red', '#00AA00'))
Scale colour type _colour_identity

Manually set the colours for a categorical variable. One of the colours is a named colour, the other is a hex code.

CO2 <- CO2 %>%
    mutate(cUptake = cut(uptake,
                         breaks = c(0,15,30,46),
                         labels = c("red", "#00AA00", 1)))
ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(colour = cUptake)) +
    scale_colour_identity(labels = c('Low', 'Medium', 'High'),
                          guide = 'legend')

Alpha

alpha is used to represent the opacity of lines and solid symbols. An alpha value of 0 is transparent and an alpha value of 1 is fully opaque.

Show attributes
Parameter default
range - output range of alpha values c(0.1,1)
Feature scale Notes Example plot
Scale alpha type _alpha_continuous

Manually define a narrower alpha scale.

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(alpha = uptake)) +
    scale_alpha_continuous(range = c(0.5, 1))
Scale alpha type _alpha_discrete

Alpha (transparency) determined by categorical variable(s).

ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(alpha = interaction(Treatment, Type))) +
    scale_alpha_discrete()
Scale alpha type _alpha_manual

Alpha (transparency) determined manually for a categorical variable(s).

CO2 <- CO2 %>%
    mutate(cUptake = cut(uptake,
                         breaks = c(0,15,30,46),
                         labels = c("red", "#00AA00", 1)))
ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(alpha = cUptake)) +
    scale_alpha_manual(values = c(0.3, 0.6, 0.95))
Scale alpha type _alpha_identity

Alpha (transparency) determined manually for a categorical variable(s).

CO2 <- CO2 %>%
    mutate(cUptake = cut(uptake,
                         breaks = c(0,15,30,46),
                         labels = c(0.3, 0.6, 0.95)),
           cUptake = as.numeric(as.character(cUptake)))
ggplot(data = CO2, aes(x = conc, y = uptake)) +
    geom_point(aes(alpha = cUptake)) +
    scale_alpha_identity()

Facets (panels)

Faceting splits the data up into a matrix of panels on the basis of one or more categorical vectors. Since facets display subsets of the data, they are very useful for examining trends in hierarchical designs. There are two faceting function, that reflect two alternative approaches:

  • facet_wrap(~cell) - creates a set of panels based on a factor and wraps the panels into a 2-d matrix. cell represents a categorical vector or set of categorical vectors
  • facet_wrap(row~column) - creates a set of panels based on a factor and wraps the panels into a 2-d matrix. row and column represents the categorical vectors used to define the rows and columns of the matrix respectively

Wrapped and gridded facets share a number of parameters:

  • facet - variables defining rows/columns of the grid. This can be either a formula or vector. Note, this is not deprecated for facet_grid

  • nrow - number of grid rows

  • ncol - number of grid columns

  • scales - one of “fixed” (default, axes the same across all panels), “free” (axes unique per panel), “free_x” (x-axes free), “free-y” (y-axes free)

    Explore

    g <- ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point()

    Fixed axes scales

    Free axes scales

    g + facet_wrap(~Plant, scales='fixed')

    g + facet_wrap(~Plant, scales='free')
  • as.table - if TRUE (default), arranged from top left to bottom right, otherwise, from bottom left to top right

  • drop - whether to drop factor combinations that lack data (default TRUE)

  • shrink - whether to shrink axes scales to match applied statistics (TRUE, default) or raw data (FALSE)

  • labeller - a function that determines the format of facet (strip) labels (default, ‘label_value’)

    Explore

    g <- ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point()

    Default labelling

    Append variable name to labels

    g + facet_wrap(~Plant,
                   labeller = 'label_value')

    g + facet_wrap(~Plant,
                   labeller = 'label_both')

    Wrap long labels

    Add special characters/formatting to labels

    CO2 <- CO2 %>%
        mutate(Species = paste0('Plant from ',
                                Type))
    g <- ggplot(data = CO2,
           aes(x = conc, y = uptake)) +
        geom_point()
    g + facet_wrap(~Species,
           labeller = label_wrap_gen(5))

    CO2 <- CO2 %>%
        mutate(species = paste0('italic(', Type,
                                '.spp)'))
    g <- ggplot(data = CO2,
                aes(x = conc, y = uptake)) +
        geom_point()
    g + facet_wrap(~species,
                   labeller = 'label_parsed')
  • switch - alternative positions for the panel strips (‘x’: move top labels to bottom, ‘y’: move right labels to left, ‘both’: move both top and right labels to bottom and left)

  • dir - direction in which to wrap panels (‘h’: horizontally’, ‘v’: vertically)

    Explore

    g <- ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point()

    Wrap panels horizontally

    Wrap panels vertically

    g + facet_wrap(~Plant)

    g + facet_wrap(~Plant, dir = 'v')
  • strip.position - position of the panel label (‘top’,‘bottom’, ‘left’, ‘right’)

    Explore

    g <- ggplot(data = CO2, aes(x = conc, y = uptake)) +
        geom_point()

    Strip labels on top

    Strip labels on right

    g + facet_wrap(~Plant)

    g + facet_wrap(~Plant, strip.position = 'right')

Facet wrap

Show attributes
Parameter default
nrow - number of grid rows NULL
ncol - number of grid columns NULL
dir - direction in which to wrap panels (‘h’: horizontally’, ‘v’: vertically) ‘h’
strip.position - position of the panel label (‘top’,‘bottom’, ‘left’, ‘right’) ‘top’
Feature facet Notes Example plot
Facet wrap _wrap

Matrix of panels split by a single categorical vector

ggplot(CO2, aes(y=uptake, x=conc)) +
  geom_smooth() +
  geom_point() +
  facet_wrap(~Plant)
Facet wrap _wrap

Matrix of panels split by a single categorical vector and wrap the panels vertically

ggplot(CO2, aes(y=uptake, x=conc)) +
  geom_smooth() +
  geom_point() +
  facet_wrap(~Plant, dir = 'v')
Facet wrap _wrap

Matrix of panels split by two categorical vectors

ggplot(CO2, aes(y=uptake, x=conc)) +
  geom_smooth() +
  geom_point() +
  facet_wrap(~Treatment + Type,
             labeller = labeller(Treatment = label_both,
                                 Type = label_both,
                                 multi_line = FALSE))
Facet wrap _wrap

Matrix of panels split by a single categorical vector with strip labels moved right of panels

ggplot(CO2, aes(y=uptake, x=conc)) +
  geom_smooth() +
  geom_point() +
  facet_wrap(~Plant, strip.position = 'right')

Facet grid

Show attributes
Parameter default
rows - variables used to faceting for the rows NULL
cols - variables used to faceting for the columns NULL
space - whether all panels are the same size (‘fixed’) or proportional to the scale of associated data (‘free’, ‘free_x’, ‘free_y’) ‘fixed’
margins - whether to include marginal summaries or which variables to associate marginal summaries for FALSE
Feature facet Notes Example plot
Facet wrap _wrap

Matrix of panels split by two categorical vectors

ggplot(CO2, aes(y=uptake, x=conc)) +
  geom_smooth() +
  geom_point() +
    facet_grid(rows = vars(Treatment),
               cols = vars(Type))
Facet grid _grid

Matrix of panels split by two categorical vectors

ggplot(CO2, aes(y=uptake, x=conc)) +
    geom_smooth() +
    geom_point() +
    facet_grid(rows = vars(Treatment),
               cols = vars(Type),
               margins = TRUE)
Facet grid _grid

Matrix of panels split by two categorical vectors

ggplot(CO2, aes(y=uptake, x=conc)) +
    geom_smooth() +
    geom_point() +
    facet_grid(rows = vars(Type),
               cols = vars(Treatment),
               space = 'free')

Themes

Themes govern the overall style of the graphic. In particular, they control:

  • the look and positioning of the axes (and their ticks, titles and labels)
  • the look and positioning of the legends (size,alignment, font, direction)
  • the look of plots (spacing and titles)
  • the look of panels (background, grid lines)
  • the look of panels strips (background, alignment, font)
Feature Theme Notes Example plot
Black and white theme _bw

Black and white theme

ggplot(CO2, aes(y=uptake, x=conc)) +
    geom_point() +
    theme_bw()
Classic theme _classic

Black and white theme

ggplot(CO2, aes(y=uptake, x=conc)) +
    geom_point() +
    theme_classic()
Classic theme _grey

Grey theme

ggplot(CO2, aes(y=uptake, x=conc)) +
    geom_point() +
    theme_grey()
Minimal theme _grey

Minimal theme

ggplot(CO2, aes(y=uptake, x=conc)) +
    geom_point() +
    theme_minimal()
Empty (void) theme _void

Minimal theme

ggplot(CO2, aes(y=uptake, x=conc)) +
    geom_point() +
    theme_void()

Along with these pre-fabricated themes, it is possible to create your own theme. This is done via the theme() function. Non-data themable elements comprise of either a line, rectangle or text. Therefore, they can all be modified via one of the following functions:

  • element_blank() - remove the element
  • element_line() - set the properties of a line
  • element_rect() - set the properties of a rectangle
  • element_text() - set the properties of text

The spacing around elements is defined by margin(). The sizes of elements can be directly supplied or defined relative to the size of the parent element via the rel() function.

Show attributes
Parameter _line _rect _text
inherit.blank - FALSE FALSE FALSE
fill - element fill colour NULL
colour - line/border colour NULL NULL NULL
size - line/border line size (mm) or font size (pt) NULL NULL NULL
linetype - line type (1:8, name or hex string) NULL NULL
lineend - line end style (round, butt, square) NULL
arrow - arrow specification NULL
family - font family NULL
face - font face (plain, italic, bold, bold.italic) NULL
hjust - horizontal justification (in [0, 1]) NULL
vjust - vertical justification (in [0, 1]) NULL
angle - angle (in [0, 360]) NULL
lineheight - height of a line of text NULL
margin - spacing around text (see margin()) NULL
debug - if TRUE draws a rectangle behind text and a point at anchor NULL

To get an appreciation of the theme elements controlled by a theme, enter the associated function at the command prompt (note, most themes build upon the default ‘grey’ theme):

theme_grey()
see output
## List of 93
##  $ line                      :List of 6
##   ..$ colour       : chr "black"
##   ..$ size         : num 0.5
##   ..$ linetype     : num 1
##   ..$ lineend      : chr "butt"
##   ..$ arrow        : logi FALSE
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_line" "element"
##  $ rect                      :List of 5
##   ..$ fill         : chr "white"
##   ..$ colour       : chr "black"
##   ..$ size         : num 0.5
##   ..$ linetype     : num 1
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_rect" "element"
##  $ text                      :List of 11
##   ..$ family       : chr ""
##   ..$ face         : chr "plain"
##   ..$ colour       : chr "black"
##   ..$ size         : num 11
##   ..$ hjust        : num 0.5
##   ..$ vjust        : num 0.5
##   ..$ angle        : num 0
##   ..$ lineheight   : num 0.9
##   ..$ margin       : 'margin' num [1:4] 0points 0points 0points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : logi FALSE
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ title                     : NULL
##  $ aspect.ratio              : NULL
##  $ axis.title                : NULL
##  $ axis.title.x              :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : NULL
##   ..$ vjust        : num 1
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 2.75points 0points 0points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.title.x.top          :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : NULL
##   ..$ vjust        : num 0
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 0points 0points 2.75points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.title.x.bottom       : NULL
##  $ axis.title.y              :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : NULL
##   ..$ vjust        : num 1
##   ..$ angle        : num 90
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 0points 2.75points 0points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.title.y.left         : NULL
##  $ axis.title.y.right        :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : NULL
##   ..$ vjust        : num 0
##   ..$ angle        : num -90
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 0points 0points 0points 2.75points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.text                 :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : chr "grey30"
##   ..$ size         : 'rel' num 0.8
##   ..$ hjust        : NULL
##   ..$ vjust        : NULL
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : NULL
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.text.x               :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : NULL
##   ..$ vjust        : num 1
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 2.2points 0points 0points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.text.x.top           :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : NULL
##   ..$ vjust        : num 0
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 0points 0points 2.2points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.text.x.bottom        : NULL
##  $ axis.text.y               :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : num 1
##   ..$ vjust        : NULL
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 0points 2.2points 0points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.text.y.left          : NULL
##  $ axis.text.y.right         :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : num 0
##   ..$ vjust        : NULL
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 0points 0points 0points 2.2points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ axis.ticks                :List of 6
##   ..$ colour       : chr "grey20"
##   ..$ size         : NULL
##   ..$ linetype     : NULL
##   ..$ lineend      : NULL
##   ..$ arrow        : logi FALSE
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_line" "element"
##  $ axis.ticks.x              : NULL
##  $ axis.ticks.x.top          : NULL
##  $ axis.ticks.x.bottom       : NULL
##  $ axis.ticks.y              : NULL
##  $ axis.ticks.y.left         : NULL
##  $ axis.ticks.y.right        : NULL
##  $ axis.ticks.length         : 'simpleUnit' num 2.75points
##   ..- attr(*, "unit")= int 8
##  $ axis.ticks.length.x       : NULL
##  $ axis.ticks.length.x.top   : NULL
##  $ axis.ticks.length.x.bottom: NULL
##  $ axis.ticks.length.y       : NULL
##  $ axis.ticks.length.y.left  : NULL
##  $ axis.ticks.length.y.right : NULL
##  $ axis.line                 : list()
##   ..- attr(*, "class")= chr [1:2] "element_blank" "element"
##  $ axis.line.x               : NULL
##  $ axis.line.x.top           : NULL
##  $ axis.line.x.bottom        : NULL
##  $ axis.line.y               : NULL
##  $ axis.line.y.left          : NULL
##  $ axis.line.y.right         : NULL
##  $ legend.background         :List of 5
##   ..$ fill         : NULL
##   ..$ colour       : logi NA
##   ..$ size         : NULL
##   ..$ linetype     : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_rect" "element"
##  $ legend.margin             : 'margin' num [1:4] 5.5points 5.5points 5.5points 5.5points
##   ..- attr(*, "unit")= int 8
##  $ legend.spacing            : 'simpleUnit' num 11points
##   ..- attr(*, "unit")= int 8
##  $ legend.spacing.x          : NULL
##  $ legend.spacing.y          : NULL
##  $ legend.key                :List of 5
##   ..$ fill         : chr "grey95"
##   ..$ colour       : logi NA
##   ..$ size         : NULL
##   ..$ linetype     : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_rect" "element"
##  $ legend.key.size           : 'simpleUnit' num 1.2lines
##   ..- attr(*, "unit")= int 3
##  $ legend.key.height         : NULL
##  $ legend.key.width          : NULL
##  $ legend.text               :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : 'rel' num 0.8
##   ..$ hjust        : NULL
##   ..$ vjust        : NULL
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : NULL
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ legend.text.align         : NULL
##  $ legend.title              :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : num 0
##   ..$ vjust        : NULL
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : NULL
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ legend.title.align        : NULL
##  $ legend.position           : chr "right"
##  $ legend.direction          : NULL
##  $ legend.justification      : chr "center"
##  $ legend.box                : NULL
##  $ legend.box.just           : NULL
##  $ legend.box.margin         : 'margin' num [1:4] 0cm 0cm 0cm 0cm
##   ..- attr(*, "unit")= int 1
##  $ legend.box.background     : list()
##   ..- attr(*, "class")= chr [1:2] "element_blank" "element"
##  $ legend.box.spacing        : 'simpleUnit' num 11points
##   ..- attr(*, "unit")= int 8
##  $ panel.background          :List of 5
##   ..$ fill         : chr "grey92"
##   ..$ colour       : logi NA
##   ..$ size         : NULL
##   ..$ linetype     : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_rect" "element"
##  $ panel.border              : list()
##   ..- attr(*, "class")= chr [1:2] "element_blank" "element"
##  $ panel.spacing             : 'simpleUnit' num 5.5points
##   ..- attr(*, "unit")= int 8
##  $ panel.spacing.x           : NULL
##  $ panel.spacing.y           : NULL
##  $ panel.grid                :List of 6
##   ..$ colour       : chr "white"
##   ..$ size         : NULL
##   ..$ linetype     : NULL
##   ..$ lineend      : NULL
##   ..$ arrow        : logi FALSE
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_line" "element"
##  $ panel.grid.major          : NULL
##  $ panel.grid.minor          :List of 6
##   ..$ colour       : NULL
##   ..$ size         : 'rel' num 0.5
##   ..$ linetype     : NULL
##   ..$ lineend      : NULL
##   ..$ arrow        : logi FALSE
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_line" "element"
##  $ panel.grid.major.x        : NULL
##  $ panel.grid.major.y        : NULL
##  $ panel.grid.minor.x        : NULL
##  $ panel.grid.minor.y        : NULL
##  $ panel.ontop               : logi FALSE
##  $ plot.background           :List of 5
##   ..$ fill         : NULL
##   ..$ colour       : chr "white"
##   ..$ size         : NULL
##   ..$ linetype     : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_rect" "element"
##  $ plot.title                :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : 'rel' num 1.2
##   ..$ hjust        : num 0
##   ..$ vjust        : num 1
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 0points 0points 5.5points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ plot.title.position       : chr "panel"
##  $ plot.subtitle             :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : num 0
##   ..$ vjust        : num 1
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 0points 0points 5.5points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ plot.caption              :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : 'rel' num 0.8
##   ..$ hjust        : num 1
##   ..$ vjust        : num 1
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 5.5points 0points 0points 0points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ plot.caption.position     : chr "panel"
##  $ plot.tag                  :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : 'rel' num 1.2
##   ..$ hjust        : num 0.5
##   ..$ vjust        : num 0.5
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : NULL
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ plot.tag.position         : chr "topleft"
##  $ plot.margin               : 'margin' num [1:4] 5.5points 5.5points 5.5points 5.5points
##   ..- attr(*, "unit")= int 8
##  $ strip.background          :List of 5
##   ..$ fill         : chr "grey85"
##   ..$ colour       : logi NA
##   ..$ size         : NULL
##   ..$ linetype     : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_rect" "element"
##  $ strip.background.x        : NULL
##  $ strip.background.y        : NULL
##  $ strip.placement           : chr "inside"
##  $ strip.text                :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : chr "grey10"
##   ..$ size         : 'rel' num 0.8
##   ..$ hjust        : NULL
##   ..$ vjust        : NULL
##   ..$ angle        : NULL
##   ..$ lineheight   : NULL
##   ..$ margin       : 'margin' num [1:4] 4.4points 4.4points 4.4points 4.4points
##   .. ..- attr(*, "unit")= int 8
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ strip.text.x              : NULL
##  $ strip.text.y              :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : NULL
##   ..$ vjust        : NULL
##   ..$ angle        : num -90
##   ..$ lineheight   : NULL
##   ..$ margin       : NULL
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  $ strip.switch.pad.grid     : 'simpleUnit' num 2.75points
##   ..- attr(*, "unit")= int 8
##  $ strip.switch.pad.wrap     : 'simpleUnit' num 2.75points
##   ..- attr(*, "unit")= int 8
##  $ strip.text.y.left         :List of 11
##   ..$ family       : NULL
##   ..$ face         : NULL
##   ..$ colour       : NULL
##   ..$ size         : NULL
##   ..$ hjust        : NULL
##   ..$ vjust        : NULL
##   ..$ angle        : num 90
##   ..$ lineheight   : NULL
##   ..$ margin       : NULL
##   ..$ debug        : NULL
##   ..$ inherit.blank: logi TRUE
##   ..- attr(*, "class")= chr [1:2] "element_text" "element"
##  - attr(*, "class")= chr [1:2] "theme" "gg"
##  - attr(*, "complete")= logi TRUE
##  - attr(*, "validate")= logi TRUE