The Grammar of Graphics
Maya runs a small neighbourhood bakery, and by now she can wrangle her till data and summarise it: last week she pulled seven rows, one per day, each with the foot traffic (people who walked in) and the revenue (dollars taken). But a column of seven numbers does not show her what is going on. The moment she draws it, the story jumps out: busier days take more money, and Saturday towers over the rest.
That picture below is a ggplot. By the end of this lesson you will understand the small set of rules, the grammar, that builds it, and every other chart in this course.
By the end you will be able to:
- Name the three core parts of every ggplot: the data, the aesthetic mappings, and the geoms
- Build a plot in R by stacking
ggplot(data)+aes()+ a geom, one layer at a time with+ - Read ggplot code as a sentence, and swap one word to get a different chart
Prerequisites: you can run R and load a package with library(), and you have a data frame in hand (you built one in the dplyr and EDA sections). Every plotting term is defined as it appears.
Why "grammar"?
English has a handful of grammar rules, a subject, a verb, an object, and from them you build endless different sentences. The grammar of graphics is the same idea for charts: a small set of parts that combine to describe almost any plot you can imagine. ggplot2 is R's implementation of it, which is why a scatterplot, a line chart and a bar chart all read almost the same in code.
Three parts do most of the work, and you assemble them in layers, stacked one on top of the next with a +:
- Data - the data frame you want to picture (Maya's week).
- Aesthetic mappings - rules that connect a column to a visual channel: which column goes on the x axis, which on the y axis, which controls colour.
- Geoms - the geometric objects that actually draw the data: points, lines, bars.
Hold those three in mind; the rest of the lesson adds them one at a time.
Start with the data
Every plot is built on a data frame, so that is where the grammar starts. Each lesson runs in a fresh R session, so let us build Maya's trading week right here (run this once):
The first layer is just the data. Hand it to ggplot() and you get a blank canvas: ggplot now knows your data, but you have not told it what to map or how to draw, so there is nothing on the panel yet.
That empty grey panel is the foundation every later layer paints onto.
The aesthetic mapping
Here is the heart of the grammar. An aesthetic mapping is a rule that connects one column of your data to one visual channel of the plot: x position, y position, colour, size, or shape. You write it inside aes().
Maya wants foot traffic along the bottom and revenue up the side, so she maps foot_traffic to x and revenue to y:
Run it and something changes: the axes now read 110 to 240 across and 340 to 720 up, scaled to her actual numbers. But there are still no dots. That is the key idea to hold onto: the mapping says what goes where, not how to draw it. You have set the stage; nothing has stepped onto it yet.
The geom draws it
To actually draw the marks you add a geom, short for geometric object: the shape that turns mapped data into something you can see. geom_point() draws one point per row, placed at that row's (x, y). You add it to the mapping with a +:
Now the seven days appear, climbing from lower-left to upper-right, exactly the scatter from the cover. Data, then a mapping, then a geom: that is a complete plot.
The + is not arithmetic, it adds a layer, and you can keep stacking. Add a straight-line trend as a second layer on the very same data and mapping:
ggplot(data, aes(...)) with one or more geoms added by +. Reading it back: "take this data, map these columns to these channels, and draw them with these geoms." Master that one sentence and you can read any ggplot.Axes, but no dots
Maya runs ggplot(bakery, aes(x = foot_traffic, y = revenue)) and sees a panel with correctly scaled axes, but not a single point on it. What did she forget?
+ geom_point() and the dots appear.aes(x, y) is a perfectly complete mapping for a scatter. Colour is optional. What is missing is a geom, the layer that turns the mapping into marks.Same recipe, swap one part
Because a plot is just parts in layers, you can change one part and get a different chart from the very same data. Below is Maya's revenue across the seven days, with the same data and the same x/y mapping every time. Only the geom changes. Click between them and watch the ggplot code change by exactly one verb: geom_line(), geom_col(), geom_point().
A line traces the trend across the week, bars compare the days side by side, points mark each value. Same grammar, three answers to three different questions, one word apart.
Mapping a column vs setting a constant
There is one distinction that trips up almost everyone, and it is worth getting straight now. Putting something inside aes() maps it to a column; putting it outside aes(), directly in the geom, sets it to one fixed value.
Map colour to a column and ggplot gives each group its own colour and a legend to match. Here Maya colours by day_type, and the two weekend days light up apart from the five weekdays:
Set colour as a constant instead, outside aes(), and every point is the same fixed colour with no legend, because nothing was mapped:
aes() = mapped to data (varies by column, earns a legend). Outside aes() = a constant you set by hand (one fixed value for every mark). "Does this depend on the data?" decides which side of aes() it goes.Inside or outside aes()?
Maya wants every dot drawn in the same fixed blue, no grouping, no legend. Where should colour = "steelblue" go?
aes(). It is set, not mapped, so there is no legend and all points share the one fixed colour.aes() sets one fixed colour for all points; inside aes() maps colour to data and triggers a legend with a colour ggplot chooses. The placement is the whole point.Finish the plot
You have the mapping; add the layer that draws the marks. Complete this scatter of Maya's revenue against foot traffic with the geom that draws one point per row.
Show answer
ggplot(bakery, aes(x = foot_traffic, y = revenue)) +
geom_point()References
A few authoritative places to take this further:
- ggplot2: Elegant Graphics for Data Analysis (3rd ed, free online) - the canonical book; its opening chapters lay out the grammar you just met, by the package's author.
- Wickham (2010), A Layered Grammar of Graphics - the paper that defines the layered grammar ggplot2 implements; short and very readable.
- R for Data Science (2e): Data visualisation - the gentlest hands-on tour of
ggplot(),aes()and geoms, with exercises. - ggplot2 package documentation - the reference for every geom, aesthetic and scale, plus the one-page cheatsheet.
Lesson 1 complete
You can now read a ggplot as a sentence. Every chart in this course is the same three parts in layers: the data, the aesthetic mappings that connect columns to visual channels inside aes(), and the geoms added with + that draw the marks. You built one up layer by layer, watched the same data become a line, bars and points by swapping a single geom, and learned the trap that catches beginners, mapping inside aes() versus setting a constant outside it.
Next, Lesson 2: Scatter and line charts in ggplot2. You will take geom_point() and geom_line() further, map a third variable to colour and size, and add a trend line that summarises the whole cloud, the workhorses you will reach for most.