1NDMC, EPHI 2DMU & C4ED
April 28 – May 1, 2026

By the end of this module you will be able to:
ggplot() + geom_*()
ggsave()
ggplot2 is built on a coherent Grammar of Graphics:
Note
In public health: the same ggplot2 skills apply whether you’re mapping disease burden, plotting age pyramids, or presenting outbreak curves.
x, y, colour … (aes())geom_*())facet_wrap())stat_*())coord_*())theme())
| Aesthetic | What it controls |
|---|---|
x, y
|
Position on axes |
colour |
Outline / point colour |
fill |
Interior fill colour |
size |
Size of points / lines |
shape |
Point shape (0–24) |
alpha |
Transparency (0 = invisible, 1 = opaque) |
linetype |
Solid, dashed, dotted, etc. |
The general syntax is:
ggplot(data = data, mapping = aes(mapings))+ geom_function()
Geom Components
| Geom | Description | Input |
|---|---|---|
geom_histogram |
Histograms | Continous x |
geom_bar |
Bar plot with frequncies | Discrete x |
geom_point |
Points/scattorplots | Discrete/continuous x and y |
geom_boxplot |
Box plot | Disc. x and cont. y |
geom_smooth |
Adds a smoothed conditional mean / regression line | Continuous x and y |
geom_line |
Line plots | Discrete/continuous x and y |
geom_abline |
Reference | line intercept and slope value |
geom_hline, geom_vline
|
Horizontal and vertical reference lines | yintercept or xintercept |
Every ggplot follows this pattern:
The three required components:
| Component | Function | Example |
|---|---|---|
| Data | The data frame | data = penguins |
| Aesthetic | Map variables to visual properties | aes(x = species, y = body_mass_g) |
| Geometry | The type of plot | geom_boxplot() |
We use the penguins dataset (Palmer Archipelago, Antarctica) as a familiar reference before applying skills to surveillance data.
geom_bar()
Tip
fct_infreq() orders bars by frequency — always more informative than alphabetical ordering.
geom_histogram()
Tip
Density plots are ideal for comparing distributions when group sizes differ — common in age-stratified epidemiology.
Facets create a separate panel for each level of a grouping variable.
ggplot(penguins,
aes(x = flipper_length_mm, y = body_mass_g,
colour = species)) +
geom_point(alpha = 0.7) +
facet_wrap(~species) +
labs(title = "Flipper Length vs. Body Mass by Island",
x = "Flipper Length (mm)", y = "Body Mass (g)") +
theme_minimal(base_size = 13) +
theme(legend.position = "bottom")# Using measles data
measles_ts_data <- read_csv("data/measles_ts_data.csv", show_col_types = FALSE)
measles_ts_data |>
ggplot(aes(x = date, y = measles_total)) +
geom_line(color = "steelblue", linewidth = 0.9) +
geom_point(color = "steelblue", size = 0.6) +
labs(title = "Monthly Measles Cases (2012-2024)",
x = "Date", y = "Total cases (monthly)") +
scale_x_date(date_breaks = "2 year", date_labels = "%Y") +
theme_minimal(base_size = 14)Key theme() elements for polished slides and reports:
ggplot(penguins, aes(x = fct_rev(fct_infreq(species)), fill = species)) +
geom_bar(show.legend = FALSE, width =0.7) +
geom_text(stat = "count",
aes(label = after_stat(count)),
vjust = -0.5, fontface = "bold", size = 4) +
labs(title = "Penguin Species Count",
x = "Species", y = "Count") +
scale_fill_manual(
values = c("Adelie" = "#1f77b4", "Chinstrap" = "#ff7f0e",
"Gentoo" = "#2ca02c")) +
theme_minimal(base_size = 14) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5, size = 16),
axis.text = element_text(size = 12)
)ggsave()
# Assign your plot to an object
my_plot <- ggplot(penguins,
aes(x = flipper_length_mm, y = body_mass_g,
colour = species)) +
geom_point() +
theme_minimal()
# Save it
ggsave(
filename = "figures/penguin_scatter.png",
plot = my_plot,
width = 8,
height = 5,
dpi = 300 # 300 dpi for publication quality
)Task: Create a customised bar chart showing the count of students by race/ethnicity (race4).
Requirements:
race4 before plotting.theme_minimal() with increased base font size.
Using measles_clean (from Module 2):
#D62828
labs()
✅ ggplot2 builds plots layer by layer: data → aesthetics → geometry
✅ Chart selection depends on variable type (categorical, numerical, time)
✅ facet_wrap() creates small multiples for group comparison
✅ theme() gives full control over plot appearance
✅ ggsave() saves print-ready figures at 300 dpi
✅ ggplotly() converts any ggplot to an interactive visualisation
Resources