Lesson 1 of 3

Facets & Scales

Maya the neighbourhood baker did well enough to open two more branches. She now runs three: Downtown, Riverside, and the new one inside the Airport. Each branch logs the same two numbers every day, the foot traffic (people who walked in) and the revenue (dollars taken). When she draws all three branches on one chart, it turns into a tangle: the Airport branch is so much bigger that the other two flatten into the floor.

The fix is one of the most useful moves in all of data visualization: stop forcing every group onto one panel, and give each group its own little chart. Below is exactly that, the same data as one chart, then split into small multiples. Flip the toggle.

By the end of this lesson you will be able to:

  • Say when small multiples beat cramming every group into one panel, and what facet_wrap(~ var) does
  • Split a plot into one panel per group with facet_wrap(), and one panel per combination with facet_grid()
  • Choose fixed vs free panel scales without misleading your reader, and bend the axis, guides and legend to your will

Prerequisites: you can build a basic ggplot and map a column to colour, ggplot(data, aes(...)) + geom_*() (from Data Visualization with ggplot2, especially the grammar of graphics). Every new function is defined as it appears.

The problem

When one panel has too many stories

Let us put Maya's three branches into this fresh R session. Each lesson starts clean, so the data lives right here on the page, run this block once and the rest of the lesson builds on it:

RInteractive R
library(ggplot2) set.seed(1) days <- c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun") # One row per branch per day: 3 branches x 7 days = 21 rows. # Airport is a much bigger shop, so its revenue dwarfs the other two. sales <- data.frame( branch = rep(c("Downtown", "Riverside", "Airport"), each = 7), day = factor(rep(days, times = 3), levels = days), foot_traffic = c(150, 165, 180, 205, 240, 300, 260, # Downtown 95, 110, 120, 140, 175, 220, 190, # Riverside 520, 560, 610, 680, 760, 980, 880), # Airport revenue = c(300, 330, 360, 430, 520, 690, 600, # Downtown 190, 210, 240, 280, 360, 470, 410, # Riverside 2100, 2300, 2520, 2900, 3300, 4200, 3700) # Airport ) head(sales) #> branch day foot_traffic revenue #> 1 Downtown Mon 150 300 #> 2 Downtown Tue 165 330 #> 3 Downtown Wed 180 360 #> 4 Downtown Thu 205 430 #> 5 Downtown Fri 240 520 #> 6 Downtown Sat 300 690

  

The instinct is to map branch to colour and draw all 21 points on one panel. Try it and you hit a wall: Airport's revenue runs into the thousands while Riverside barely clears a few hundred, so the shared y-axis stretches to fit Airport and crushes the other two branches into a flat band at the bottom. Worse, the points pile on top of each other (that is overplotting), so even the colours cannot rescue it. The widget below is that crowded one-panel chart, three branches, one squashed scale.