Introduction

WarningCaution

This section is still being developed. The contents are subject to change.

ggplot2 syntax

“making infinite use of finite means” (Wilhelm von Humboldt)

Every language has rules for what words mean and how to order them.1 R is a language for working with data, and ggplot2 follows R’s rules:

  • a thing that holds data is like a naming word, and

  • the set of steps that does something to that thing is like a doing word2

A graph is a picture of data that we make with code. ggplot2 graphs are built one layer at a time. A layer is one part of a graph that we put on top of the parts under it. We can start with a few layers and keep adding more until the graph is just what we want.3

The Data Layer

The data layer is a table, like a page of numbers on a computer.4 A column is one list of values that runs down a table, and a row is one line across it. Every set of data in this book is made up,5 so we’ll make one here: 150 home computers sold in 1998, with the company that made each computer (brand), the system it runs (os), how fast it works (cpu_mhz), and its price (price_usd).6 Faster computers cost more, and newer systems add a little to the price.7

show/hide
set.seed(1998)
pc_sales <- tibble(
  brand = sample(c("Compaq", "Dell", "Gateway"), 150, replace = TRUE),
  os = sample(c("Windows 95", "Windows 98"), 150, replace = TRUE, 
    prob = c(0.4, 0.6)),
  cpu_mhz = sample(c(133, 166, 200, 233, 266, 300, 350, 400), 150, 
    replace = TRUE),
  price_usd = round(700 + 4 * cpu_mhz + 
    if_else(os == "Windows 98", 150, 0) + rnorm(150, 0, 200)))
ggplot(data = pc_sales)

The Mapping Layer

The mapping layer joins columns in the data to things we can see in the graph, such as how far across and how far up each point goes. An axis is a number line along one side of a graph.8

show/hide
ggplot(data = pc_sales,
  mapping = 
    aes(
      x = cpu_mhz, y = price_usd
      )
  )

Plan 1: data, mapping, and one way to show the data9

ggplot(data = <DATA>) +
  geom_*(mapping = aes(<AESTHETIC MAPPINGS>))

The Stats/Geoms Layer

The geom_*() parts of the code pick how to show the data in the graph: as points, lines, bars, and more.10 They can also work out new numbers from the data before they show it,11 and move things so they don’t cover each other.12

show/hide
ggplot(data = pc_sales,
  mapping = aes(
    x = cpu_mhz, y = price_usd
    )
  ) +
  geom_point(
    aes(
      shape = brand, color = os
      )
    )

We can put many layers (data, mapping, and ways to show the data) in one graph.

show/hide
ggplot(data = pc_sales,
 # layer 1
  mapping = aes(
    x = cpu_mhz, y = price_usd
    )
  ) +
  geom_point(
    aes(
      shape = brand, color = os
      )
    ) +
# layer 2
  geom_smooth(
    mapping = aes(
      x = cpu_mhz, y = price_usd), 
        se = FALSE
    )

Plan 2: Plan 1 + a second way to show the data13

ggplot(data = <DATA>) +
    geom_*(mapping = aes(<AESTHETIC MAPPINGS>)) +
    geom_*(mapping = aes(<AESTHETIC MAPPINGS>))

Position, Labels & Themes

With a set number of things and steps, we can put the rules of ggplot2 together to make graphs without end.14

show/hide
ggplot(data = pc_sales,
 # layer 1
  mapping = aes(
    x = cpu_mhz, y = price_usd
    )
  ) +
  geom_point(
    aes(
      color = os
      )
    ) +
# layer 2
  geom_smooth(
    mapping = aes(
      x = cpu_mhz, y = price_usd), 
        se = FALSE
    ) +
# layer 3
  facet_wrap(
    . ~ brand, ncol = 2
    ) + 
  # labels
  labs(
    x = 'Processor speed (MHz)', y = 'Price (USD)', 
    title = 'Home PCs in 1998',  subtitle = 'Faster processors cost more',
    caption = 'Simulated data', color = 'Operating system'
    ) + 
  # themes
  theme(legend.position = "bottom", legend.box = "vertical")

Plan 3: Plan 2 + small graphs, a new look, and words15

ggplot(data = <DATA>) +
    geom_*(mapping = aes(<AESTHETIC MAPPINGS>)) +
    geom_*(mapping = aes(<AESTHETIC MAPPINGS>)) +
    facet_* +
    theme() +
    labs()

Graph Categories

Each graph in this book is in one of the groups below (you can see them in the list of parts on the left side of the page).

  • Univariate: graphs of one column16

  • Amounts: how many, or a few simple numbers that stand for one or two columns17

  • Proportions: how the parts of something make up the whole18

  • Distributions: where the values in one column fall, and the form they take19

  • Dates & Times: how numbers or groups change over time (by day, month, year, and so on)20

  • Relationships: how a change in the values of x goes with a change in the values of y (and sometimes z)

Some graphs could fit in more than one group. Where that’s true, I’ve tried to add links in the notes to the other places they fit.

Assumptions

I’ve tried to write code that you can read and understand without running it.21 Still, the examples expect you to be able to look inside things in R and answer questions about how they’re built.22

Style & structure

Each graph has the parts below:

  1. Theme

    • The look we give every graph on the page: its colors, its letters, and the old thing it takes them from.
  2. Requirements

    • What this graph needs, and a first look at it.
  3. Description

    • A short note on where the graph comes from, what it’s for, and what we see in it.
  4. Set up

    • Packages
      • Code to get the newest form of the code we use, when we need it.23
    • Data
      • The code that makes up the data for the graph (with set.seed(), so you get the same values every time).
  5. Distribution

    • How the rule we used to make up the data gives the graph its form, in three steps:24
      • COUNT IT: look at a few values and a few numbers that stand for all of them.
      • DRAW IT: show the data as a bar model or as a graph with notes on it.
      • NAME IT: write down the rule and show what each number in it does to the graph.25
  6. Grammar

    • Graph Code
      • The words around the graph start with labs_
      • The graph layers start with ggp2_
  7. More info

    • Other ways to make the graph, other choices, and other uses26
      • Sets of colors
      • Other code that works well with it

The picture below shows how the parts fit together. We make up the data in Set up, talk about it in Distribution, and turn it into a graph in Grammar.

%%{init: {'theme': 'base', 'themeVariables': { 'fontFamily': 'monospace', 'fontSize': '14px', 'darkMode': false}}}%%

flowchart TD
    thm(["<strong>Theme</strong><br>colors + letters"]) --> req(["<strong>Requirements</strong><br>what the graph needs"]) --> desc["<strong>Description</strong><br>what the graph shows"]
    desc --> setup[/"<strong>Set up</strong><br>packages + simulated data"/]
    setup --> dist
    subgraph dist["<strong>Distribution</strong>"]
        count["i. COUNT IT<br>values + summaries"] --> draw["ii. DRAW IT<br>bar model or<br>annotated graph"]
        draw --> name["iii. NAME IT<br>distribution +<br>parameters"]
    end
    dist --> grammar[["<strong>Grammar</strong><br><code>labs_*</code> + <code>ggp2_*</code>"]]
    grammar --> more(["<strong>More info</strong><br>other geoms + options"])

    style thm fill:#4CBB9D,color:#FFFFFF,rx:5,ry:5
    style req fill:#4CBB9D,color:#FFFFFF,rx:5,ry:5
    style desc fill:#FFFFFF,color:#000000,stroke:#333
    style setup fill:#C0C0C0,color:#000000,stroke:#333
    style dist fill:#FFFFFF,color:#000000,stroke:#333,stroke-width:1px,rx:10,ry:10
    style count fill:#000080,color:#FFFFFF,rx:5,ry:5
    style draw fill:#000080,color:#FFFFFF,rx:5,ry:5
    style name fill:#000080,color:#FFFFFF,rx:5,ry:5
    style grammar fill:#FFFFFF,color:#000000,stroke:#333
    style more fill:#4CBB9D,color:#FFFFFF,rx:5,ry:5

The sections in each graph chapter

I’ve tried to keep things short and clear, but when I have to pick one, I pick clear. I’ve also followed a general rule: if one of the geom_* steps in ggplot2 can build a graph easily, I show that way first.

The first part of the book starts with bar graphs, which show how many times each group shows up in one column.


  1. Grammar is the system of rules for a language (word meanings, internal structure, and word order). Syntax is the form, structure, and order used to build statements.↩︎

  2. Objects are like nouns, and functions are like verbs (functions “do things” to objects).↩︎

  3. Layers work like templates we can use to build increasingly customized and complex graphs.↩︎

  4. A rectangular object (like a spreadsheet) with columns and rows.↩︎

  5. Simulated.↩︎

  6. os is the operating system (Windows 95 or Windows 98), and cpu_mhz is the processor speed in megahertz.↩︎

  7. Windows 98 adds $150 to the price compared with Windows 95.↩︎

  8. The mapping layer assigns columns (variables) to visual properties, or aesthetics, with aes(). Here cpu_mhz goes on the x axis and price_usd goes on the y axis.↩︎

  9. Basic template: data, aesthetic mappings, and a geom.↩︎

  10. Geoms (geometric objects), like geom_point(), geom_line(), and geom_bar().↩︎

  11. Statistical transformations, like counting values for a bar graph or fitting a smooth line.↩︎

  12. Position adjustments, like stacking or dodging bars.↩︎

  13. Template + 1 layer: more geoms and more aesthetic mappings.↩︎

  14. With a finite number of objects and functions, we can combine the grammar and syntax of ggplot2 to create an infinite number of graphs (see the quote above).↩︎

  15. Template + 2 layers + facets + theme + labels. facet_wrap() splits the graph into small panels (one per brand), theme() changes the look (here, where the legend goes), and labs() adds the labels.↩︎

  16. A single variable.↩︎

  17. Counts or simple summary statistics.↩︎

  18. Part to whole ratios.↩︎

  19. The shape of a variable’s values (normality, skewness, kurtosis, etc.).↩︎

  20. Changes in quantitative or categorical variables over a time dimension (date-time, date, year, month, quarter, etc.).↩︎

  21. This field manual follows The Rule of Least Power, in the sense that “a language with a straightforward syntax may be easier to analyze than an otherwise equivalent one with more complex structure.”↩︎

  22. If not, I highly recommend the skimr and inspectdf packages for getting to know your data better.↩︎

  23. Installing development versions of packages (if necessary).↩︎

  24. How the distribution we simulated from shapes the graph.↩︎

  25. Write down the distribution and connect each parameter to the graph.↩︎

  26. Additional methods, arguments, or applications.↩︎