Using ggplot2: The grammar of graphics
2026-09-09
Hosmer & Lemeshow’s low birth weight study, as an Excel file in your data/ folder.
Rows: 189
Columns: 10
$ low <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ age <dbl> 19, 33, 20, 21, 18, 21, 22, 17, 29, 26, 19, 19, 22, 30, 18, 18, …
$ lwt <dbl> 182, 155, 105, 108, 107, 124, 118, 103, 123, 113, 95, 150, 95, 1…
$ race <dbl> 2, 3, 1, 1, 1, 3, 1, 3, 1, 1, 3, 3, 3, 3, 1, 1, 2, 1, 3, 1, 3, 1…
$ smoke <dbl> 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0…
$ ptl <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0…
$ ht <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0…
$ ui <dbl> 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1…
$ ftv <dbl> 0, 3, 1, 2, 0, 0, 1, 1, 1, 0, 0, 1, 0, 2, 0, 0, 0, 3, 0, 1, 2, 3…
$ bwt <dbl> 2523, 2551, 2557, 2594, 2600, 2622, 2637, 2637, 2663, 2665, 2722…
import() picks the reader from the file extension — one function for .csv, .xlsx, .dta, .sav. here() builds the path from your project root, so it works on any machine.
clean_names(): lower case, underscores, no spaces or dots.
case_when() turns codes into words. Label before you plot — the figure inherits whatever you leave in the data.
data + mapping + geometry
aes() — which column goes on which axisgeom_ — what marks appear+ joins layers. |> moves data.Swap them and R gives a long, unhelpful error. Everyone does this in the first week.
aes() or outside?| You write | It means |
|---|---|
aes(fill = smoke) |
Colour is mapped to a column |
geom_point(colour = "navy") |
Colour is fixed decoration |
A legend with one meaningless entry means you put a constant inside aes().
| You have | Use | Not |
|---|---|---|
| One continuous | histogram, density | pie |
| One categorical | bar of counts | pie |
| Continuous by group | box + points | bar + error bar |
| Two continuous | point, + smooth | line |
| Long labels | coord_flip() |
rotated text |
One question per plot. If you cannot say the question, you cannot choose the geom.
scale_fill_viridis_d() is safe by defaultIf the figure still works in black and white, colour was a bonus, not a crutch.
labs(
title = "Birth weight by maternal smoking",
subtitle = "189 births; dashed line marks low birth weight (2500 g)",
y = "Birth weight (g)", x = NULL,
caption = "Data: Hosmer & Lemeshow low birth weight study (n = 189)."
)
ggsave("output/fig1_birthweight.png",
width = 7, height = 4.5, dpi = 300, bg = "white")Never screenshot a plot.
Four exercises on the website.
Green sticky when Exercise 1 draws something.
MedEd Conclave 2026 · R & Reproducible Research