Small Multiples with Facets
Faceting splits one plot into a grid of panels by a variable — why shared scales make small multiples so powerful, and facet_wrap vs facet_grid.
Faceting splits your data into subsets and draws a separate panel for each, all sharing the same scales. The result — a grid of small, comparable charts — is one of the most effective tools in all of data visualization, and ggplot2 makes it a one-line addition.
The problem facets solve
Mapping a grouping variable to color works until there are too many groups; then the chart becomes an unreadable tangle. Watch a color mapping struggle:
Now give each class its own panel instead:
Why shared scales are the secret
The magic ingredient is that every panel uses the same x and y scales by default. Because the axes are identical, any difference you see between panels is a real difference in the data — not an artifact of different scaling. Your eye compares parallel pictures far faster than it parses one crowded picture.
The deep idea behind small multiples
Faceting works because it removes a variable from the visual clutter and turns it into spatial position (which panel). Comparison becomes effortless precisely because everything except the faceting variable is held constant across panels.
facet_wrap: one variable, wrapped into a grid
facet_wrap(~ var) lays panels out in rows and columns that "wrap"
like text. Control the shape with nrow or ncol:
facet_grid: a 2-D matrix of two variables
facet_grid(rows ~ cols) makes a true grid: one variable defines the
rows, another the columns, so every panel is a combination of both.
This is ideal for crossing two categorical variables:
Read it like a table: moving down changes drivetrain, moving across changes cylinder count. Empty panels honestly show combinations that do not occur in the data.
facet_wrap(~ a) | facet_grid(a ~ b) | |
|---|---|---|
| Variables | one (sometimes two) | two, one per dimension |
| Layout | wrapped into a grid to fit | strict rows × columns matrix |
| Best for | many levels of one variable | the crossing of two variables |
The free-scales escape hatch
Sometimes panels cover wildly different ranges and shared scales squash
some panels flat. scales = "free_y" (or "free_x", "free") lets
each panel scale independently:
Free scales break comparability
Independent scales make each panel readable on its own but destroy the cross-panel comparison that makes small multiples powerful — a tall bar in one panel may represent a smaller value than a short bar in another. Use free scales sparingly and label them clearly.
What makes faceted "small multiples" so effective for comparison?
Each panel uses a different, optimized scale.
The panels are randomly ordered to reduce bias.
All panels share the same axes by default, so any visible difference between panels reflects a real difference in the data rather than a scaling artifact.
Faceting adds a trend line to every panel automatically.
You want a grid of panels crossing two categorical variables — drivetrain down the rows and cylinder count across the columns. Which facet function fits best?
facet_wrap(~ drv + cyl).
facet_grid(drv ~ cyl), which places drivetrain on the rows and cylinders on the columns as a true matrix.
facet_grid(~ drv).
You cannot facet by two variables.
What is the main risk of setting scales = "free_y" in a faceted plot?
It will cause an error in most plots.
It hides some of the data points.
Each panel gets its own y-axis range, so panels are no longer directly comparable — equal-looking marks can represent different values.
It changes the faceting variable.
Key takeaways
- Faceting splits data into per-group panels — small multiples that the eye compares quickly.
- Panels share scales by default, so between-panel differences are real data differences.
facet_wrap(~ var)wraps one variable's levels into a grid;facet_grid(rows ~ cols)crosses two variables into a matrix.scales = "free_*"lets panels scale independently but breaks comparability — use it cautiously.
Flipping and Polar Coordinates
The grammar's most striking payoff — turning a bar chart into a pie chart by changing only the coordinate system, and flipping axes the right way.
Themes and Styling
Themes control everything that is not data — fonts, gridlines, backgrounds, legend placement — through a single, inheritance-based system.