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.
This is the page where the Grammar of Graphics earns its keep in the most visible way possible. We promised early on that a pie chart is a stacked bar chart in polar coordinates. Now you will build exactly that — changing one component and nothing else.
Flipping coordinates
coord_flip() swaps the x and y axes. It is the clean way to make
horizontal bars — useful when category labels are long and would
overlap on a vertical axis:
Notice you did not swap the mapping (x = class stayed put). You
changed the coordinate system, and the bars rotated. The chart's
meaning is identical; only its orientation changed.
A modern alternative
Recent ggplot2 also lets you map the categorical variable to y
directly (aes(y = class)) for horizontal bars. coord_flip() remains
the clearest illustration that orientation is a coordinate decision,
which is why we use it here.
From bar to pie: change one component
Now the famous transformation. Start with a single stacked bar — one bar, segmented by drivetrain:
That tall stacked bar carries all the information a pie chart does:
each segment's height is a count. Now wrap the y-axis around a
circle with coord_polar(theta = "y"). Nothing else changes:
You just made a pie chart — and you did it without a geom_pie()
(there is no such thing in ggplot2, by design). The pie is the
stacked bar, re-expressed in polar coordinates.
In Cartesian space, a count became a height. In polar space, that same count becomes an angle. Same data, same stat, same geom — only the coordinate system differs.
Bullseye: polar on the x
Mapping the other angle (theta = "x") bends the bar chart into a
circular "coxcomb" / wind-rose style — the shape Florence Nightingale
made famous:
Pies are usually a poor choice — and that is the point
ggplot2 makes pie charts deliberately awkward (no `geom_pie`) because humans judge angles far less accurately than lengths. A bar chart is almost always easier to read. The lesson here is not "make pies"; it is that the grammar reveals pies and bars to be the same chart under different coordinates — a profound conceptual point even though the pie itself is rarely the best display.
In ggplot2, how do you create a pie chart?
Call geom_pie() with the category mapped to fill.
Use coord_cartesian() on a scatter plot.
Draw a single stacked bar (count by fill) and apply coord_polar(theta = "y") so the bar's height becomes an angle.
Pies are impossible in ggplot2.
Converting a stacked bar to a pie with coord_polar() changes which grammar component, and what happens to the encoded count?
It changes the geom; the count becomes a color.
It changes the statistic; the count is recomputed.
It changes only the coordinate system; the count that was a bar height in Cartesian space becomes a slice angle in polar space.
It changes the data; rows are aggregated differently.
Why does ggplot2 deliberately make pie charts inconvenient to produce?
Pie charts are technically impossible to render in R.
To force users to pay for a premium feature.
Because people judge lengths (bars) more accurately than angles (pie slices), so the design nudges users toward more readable charts.
Because polar coordinates are not supported.
Key takeaways
coord_flip()swaps the axes — the clean way to get horizontal bars and prove orientation is a coordinate decision.- A pie chart is a single stacked bar under
coord_polar(theta="y")— a count becomes an angle instead of a height. - There is no
geom_pie()by design, because length beats angle for human perception. - Changing the coordinate system re-expresses the same data, stat, and geom — the grammar's most vivid payoff.
Cartesian and Beyond
The coordinate system is the space marks live in — usually Cartesian, but the choice is a real grammar component with real consequences.
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.