A graph is more than decoration. A graph is an argument, a claim about what the numbers mean, made in a language (position, length, color) that the eye reads faster than any sentence. And like any argument, a graph can be honest or it can mislead, sometimes without its maker even noticing. This chapter is about making the honest kind, and recognizing the other kind. It is also about what a graph can reveal: Anscombe’s quartet showed four datasets with identical statistics but four completely different shapes, a reminder that a picture often catches what a summary number hides.
The examples here come from a real project - The Sports Page, a daily newsletter (a sister project to this book) that takes one strange sports number and tells the truth about what it does and does not mean. Its house rule is the same one that runs through this whole book: describe what happened, predict what will happen, and never dress up one as the other. Good graphics are how you keep that promise to your reader.
26.1 Learning Objectives
Match the geometry of a graph to the question (trend, comparison, distribution, relationship).
Recognize how an axis can exaggerate or hide a real change - and choose an honest one.
Prefer small multiples to overloaded dual-axis charts, and ranked bars to pie charts.
Show the distribution, not just a summary, and tame overplotting.
26.2 Match the Geometry to the Question
The first decision is not color or font - it is geometry. What shape of mark answers your question? A change over time wants a line. Here is a true story: over the last four decades, major-league baseball became a strikeout sport. Watch it in one line:
Strikeouts per nine innings, MLB, 1985–present. A trend wants a line.
A line says “these points are connected in sequence” - exactly the claim you want for a time trend. A bar chart here would be wrong: bars say “these are separate categories to compare,” which is a different (and misleading) sentence. The geometry is the argument. Trend → line; category comparison → bar; one distribution → histogram; two variables → scatter. Pick the mark that makes the claim you actually mean.
26.3 Don’t Lie With the Axis
Same data, two axes, two very different impressions. Batting average has drifted down over the same period, from about .257 to about .242, a real but modest slide. First, watch a zoomed-in y-axis make that modest slide look like a catastrophe:
ggplot(mlb, aes(year, AVG)) +geom_line(color ="firebrick", linewidth =1) +coord_cartesian(ylim =c(0.242, 0.258)) +# axis zoomed to the datalabs(x =NULL, y ="AVG", title ="“Hitting is DEAD”") +theme_minimal(base_size =11)
Dishonest axis: zoomed tight, a 15-point drift looks like a cliff.
Now the exact same numbers, on an axis anchored to a meaningful baseline:
ggplot(mlb, aes(year, AVG)) +geom_line(color ="firebrick", linewidth =1) +coord_cartesian(ylim =c(0, 0.3)) +# axis from a meaningful zerolabs(x =NULL, y ="AVG", title ="“Hitting drifted down a bit”") +theme_minimal(base_size =11)
Honest axis: from a meaningful zero, the same drift is a gentle slope.
Same numbers, opposite impressions. The first axis turns a 15-point drift into what looks like a cliff; the second, anchored to a meaningful baseline, shows the truth: hitting softened, it did not collapse. Neither axis is always right. A zoomed axis is legitimate when small differences genuinely matter (and you say so), but the choice is never neutral. Ask what the axis is doing to the size of the effect, and whether that is honest.
WarningThe most common accidental lie
A truncated y-axis is the single most common way a well-meaning person makes a small effect look enormous (or the reverse). Before you publish a chart, look at your axis limits and ask: would this effect still look this big if I started from zero? If the honest version looks unremarkable, the honest answer might be that the effect is unremarkable.
26.4 Small Multiples Beat Overloaded Dual-Axis Charts
You have three trends to show at once: strikeouts, walks, and home runs per plate appearance. The temptation is to put them all on one chart with two or three y-axes. It is better not to. Dual-axis charts let you manufacture almost any relationship by rescaling one axis, and readers cannot tell which line belongs to which scale. The clearer tool is small multiples: the same chart repeated, one panel per series, on comparable axes.
long <-data.frame(year =rep(mlb$year, 3),rate =c(mlb$K_PA, mlb$BB_PA, mlb$HR_PA),kind =rep(c("Strikeouts", "Walks", "Home runs"), each =nrow(mlb)))ggplot(long, aes(year, rate)) +geom_line(color ="steelblue", linewidth =0.9) +facet_wrap(~ kind, scales ="free_y") +# one panel per serieslabs(x =NULL, y ="per plate appearance") +theme_minimal(base_size =11)
Three league trends as small multiples — comparable, honest, readable.
Each panel tells its own honest story (strikeouts soared, walks held steady, homers crept up), and no rescaling trick can fake a relationship between them. When you have many series, repeat the chart; don’t overload it.
26.5 Rank, Don’t Pie
For comparing a quantity across categories, the eye reads position along a common scale far more accurately than it reads the angles of a pie. So a bar chart beats a pie chart almost always - and a sorted bar chart beats an unsorted one, because the ordering is itself information. Which NFL teams draft worst? Thirty-two teams is already far too many for a pie; rank them:
nfl <-read.csv("data/nfl_draft_by_team.csv")ggplot(nfl, aes(x =reorder(team, rate_bust_a), y = rate_bust_a)) +geom_col(fill ="grey35") +coord_flip() +# horizontal: labels stay readablelabs(x =NULL, y ="Bust rate (no Pro Bowl)", title ="Draft busts by team") +theme_minimal(base_size =10)
NFL first-round bust rate by team — ranked bars, not a 32-slice pie.
Sorted, horizontal, one bar per team: you can read off the best and worst drafters quickly, and every team is comparable on the same axis. A pie chart of these same 32 numbers would be very hard to read; you could not tell 22% from 25% by eye, and the ranking would disappear. Pie charts work for maybe two or three slices; past that, rank a bar chart.
26.6 Show the Distribution, Not Just the Mean
A single summary number - a mean, a bar - throws away the shape of the data, and the shape is usually the story. Do not draw a bar of averages when you could draw the whole distribution. Here are this season’s qualified hitters; a histogram shows the spread of performance a mean would erase:
h <-read.csv("data/mlb_hitters_2026.csv")h <- h[h$PA >=50, ]ggplot(h, aes(OPS)) +geom_histogram(bins =30, fill ="steelblue", color ="white") +geom_vline(xintercept =median(h$OPS), color ="firebrick", linewidth =1) +labs(x ="OPS", y ="hitters", title ="Most hitters are ordinary; a few are stars") +theme_minimal(base_size =12)
The distribution of OPS across qualified hitters — the shape a single mean hides.
And when you plot two variables against each other with hundreds of points, they pile up and hide their own density. The fix is transparency (or jitter): let the dark regions show where the data actually concentrate.
ggplot(h, aes(OBP, SLG)) +geom_point(alpha =0.35, color ="steelblue") +# alpha tames overplottinglabs(x ="On-base percentage", y ="Slugging percentage") +theme_minimal(base_size =12)
On-base vs. slugging, 400+ hitters. Transparency reveals the crowd.
The cloud’s shape, with its positive drift, its dense middle, and a few outliers in the upper right, is information a table of two means could never carry. That is much of the reason graphics exist.
ImportantThe honest-graph checklist
Before a chart leaves your hands, run it past four questions:
Geometry - does the mark (line/bar/histogram/scatter) make the claim I actually mean?
Axis - would the effect look this big if I started from a meaningful zero? If not, am I saying so?
Load - am I overloading one chart (dual axes, too many series, a 32-slice pie) where small multiples or a ranked bar would be clearer?
Honesty of summary - am I hiding a distribution behind a mean, or implying a relationship the data (small \(n\), no mechanism) haven’t earned?
A graph that survives all four is an argument you can stand behind.
26.7 Challenge
TipDo One Yourself
Redraw the strikeout-revolution line with a truncated y-axis that makes the rise look even more extreme, then with a zero-based axis that makes it look tame. Which is honest, and why does “honest” depend on the question?
Take the hitters data and draw a bar chart of mean OPS by team, then a boxplot (or jittered points) of OPS by team. What does the second show that the first hides?
Find a chart in the wild (a news site, a company slide) with a truncated axis or a pie chart with too many slices. Redraw it honestly and write one sentence on what changed.
26.8 Where We Go Next
Graphics are half of how we show data; the other half is the table, and tables have their own quiet craft, their own ways of telling the truth or hiding it. That is the next chapter. Then, with tables and graphics both in hand, we turn to the payoff of this whole book: watching these tools used on real published work, with every judgment call laid bare.