
17 Pie charts
theme_koosh()
Graphs in this chapter use fmggp2::theme_koosh(), built from a tri color Koosh ball: a white background, an orange frame, orange, purple, and black filament marks, peach and lilac accents, and an Arial Rounded title.
17.1 Description
“In general, pie charts work well when the goal is to emphasize simple fractions, such as one-half, one-third, or one-quarter.”
“They also work well when we have very small datasets.” (Claus O. Wilke, Fundamentals of Data Visualization (2019))
Pie charts are ideal for comparing the proportions of categorical variable values, and we can build pie charts using the ggpubr package.
17.2 Set up
PACKAGES:
Install packages.
show/hide
install.packages("ggpubr")
library(ggpubr)
library(ggplot2)
library(dplyr) # for tibble() and data manipulationDATA:
The Koosh ball was a ball of rubber filaments that was easy to catch and impossible to bounce, and by the 90s it came in more styles than anyone needed. We’ll simulate the styles of 200 Koosh balls sold at a toy store (tri color, rainbow, neon, and glow in the dark) with sample(). The probabilities are simple fractions on purpose: one half, one quarter, one eighth, and one eighth. Then we count each style (cnt) and convert the counts to proportions (perc). Setting the seed with set.seed() means you’ll get the same 200 Koosh balls every time you run the code below.
show/hide
set.seed(1993) # same 200 Koosh balls every time the code runs
koosh_balls <- tibble(
ball_id = 1:200, # 200 different Koosh balls, one row each
style = sample(
c("Tri color", "Rainbow", "Neon", "Glow"), # four styles
size = 200, replace = TRUE, # one style for each ball
prob = c(1/2, 1/4, 1/8, 1/8) # half are Tri color
)
)
koosh_pie <- koosh_balls |>
count(style, name = "cnt") |> # balls of each style
mutate(
perc = cnt / sum(cnt), # share of all 200 balls
style = factor(style,
levels = c("Tri color", "Rainbow", "Neon", "Glow")) # most to least common
) |>
arrange(style)
glimpse(koosh_pie)
#> Rows: 4
#> Columns: 3
#> $ style <fct> Tri color, Rainbow, Neon, Glow
#> $ cnt <int> 98, 49, 23, 30
#> $ perc <dbl> 0.490, 0.245, 0.115, 0.15017.3 Distribution
A pie chart is a whole cut into slices, so it only makes sense when the slices add up to one thing (here, 200 Koosh balls). Pie charts are easiest to read when the slices are simple fractions, and because we chose those fractions in sample(), we know what each slice should look like. Below we’ll move from the Koosh balls, to a picture, to the formula.
COUNT IT:
Start with the first ten Koosh balls.
show/hide
head(koosh_balls$style, 10)
#> [1] "Tri color" "Tri color" "Tri color"
#> [4] "Rainbow" "Rainbow" "Rainbow"
#> [7] "Tri color" "Tri color" "Glow"
#> [10] "Tri color"Counting all 200 and comparing each count to the count we’d expect (200 times each fraction) shows how close the simulation lands.
show/hide
koosh_pie |>
mutate(expected = 200 * c(1/2, 1/4, 1/8, 1/8))DRAW IT:
A bar model lays the 200 Koosh balls out in a line. Tri color balls fill about half the bar, rainbow balls about a quarter, and neon and glow balls split the last quarter.
show/hide
ggplot(data = koosh_pie, aes(x = cnt, y = "200 Koosh balls",
fill = style)) +
geom_col(position = position_stack(reverse = TRUE)) +
geom_text(aes(label = cnt), color = "#FFFFFF",
position = position_stack(vjust = 0.5, reverse = TRUE)) +
labs(x = "Koosh balls", y = NULL, fill = "Style")
A pie chart bends the same bar into a circle. Below, the pie on the left uses the exact fractions from sample(), and the pie on the right uses our simulated counts. The tri color slice covers about half the circle in both, and the rainbow slice covers about a quarter.
show/hide
expected_pie <- koosh_pie |>
mutate(perc = c(1/2, 1/4, 1/8, 1/8))
ggpubr::ggpie(expected_pie, x = "perc",
label = paste0(round(100 * expected_pie$perc, 1), "%"),
lab.pos = "in", lab.font = "#FFFFFF",
fill = "style", color = "white") +
labs(title = "Expected", fill = NULL) +
pie_theme
ggpubr::ggpie(koosh_pie, x = "perc",
label = paste0(round(100 * koosh_pie$perc, 1), "%"),
lab.pos = "in", lab.font = "#FFFFFF",
fill = "style", color = "white") +
labs(title = "Simulated", fill = NULL) +
pie_theme

NAME IT:
Each Koosh ball is one draw from four styles, so the four counts follow a multinomial distribution:
\[ (N_{\text{tri color}}, N_{\text{rainbow}}, N_{\text{neon}}, N_{\text{glow}}) \sim \text{Multinomial}\left(200, \; \left(\tfrac{1}{2}, \tfrac{1}{4}, \tfrac{1}{8}, \tfrac{1}{8}\right)\right) \]
A slice’s angle is its share of the 360 degrees in the circle: \(\tfrac{1}{2}\) is 180 degrees, \(\tfrac{1}{4}\) is 90 degrees, and each \(\tfrac{1}{8}\) is 45 degrees. Simple fractions like these line up with the “clock positions” our eyes already know (half past, quarter past), which is why pie charts work best with them.
Each simulated share wobbles around its fraction by about \(\sqrt{p(1 - p) / 200}\): about 3.5 percentage points for the tri color slice and 2.3 points for the neon and glow slices. That’s why our slices are close to the expected ones but not exact. Try changing 200 to 20 in both ball_id = 1:200 and size = 200, and the slices drift much further from the simple fractions.
17.4 Grammar
CODE:
Create the slice labels (
pie_labels) withpaste0()ggpie()applies its own theme, so createpie_themeto add the book theme back (and remove the axis text, ticks, and grid lines)Create labels with
labs()Assign the data to
ggpubr::ggpie()Assign
"perc"toxAssign
pie_labelstolabelAssign
"in"tolab.posAssign white (
"#FFFFFF") tolab.fontand"white"tocolorAssign
"style"tofillAdd
pie_theme(which also moves the legend to the bottom)
show/hide
pie_labels <- paste0(round(100 * koosh_pie$perc), "%")
pie_theme <- fmggp2::theme_koosh(base_size = 14) +
theme(axis.text = element_blank(), axis.title = element_blank(),
axis.ticks = element_blank(), panel.grid.major = element_blank(),
legend.position = "bottom")
labs_pie <- labs(
title = "Koosh balls",
caption = "Simulated data",
subtitle = "Styles sold at one toy store",
fill = NULL)
ggp2_pie <- ggpubr::ggpie(koosh_pie,
x = "perc", label = pie_labels,
lab.pos = "in", lab.font = "#FFFFFF",
fill = "style", color = "white") +
pie_theme
ggp2_pie +
labs_pieGRAPH:
