Charts that split a whole into its parts, flat or nested.
| Chart | Use it when |
|---|---|
pie_chart() |
You split a whole into a few parts |
treemap_chart() |
You split a whole into many parts, optionally nested |
waffle_chart() |
You show shares as a grid of 100 squares |
sunburst_chart() |
You explore a hierarchy with several levels |
mosaic_chart() |
You show how two categorical variables combine |
rose_chart() |
You show a cyclical breakdown, such as months, Nightingale-style |
parliament_chart() |
You show seats won by each party |
pie_chart()
Pie charts and donut charts are pretty straightforward to set up.
We’ll use a sample from the starwars data frame to plot a
simple pie chart.
# starwars is part of the dplyr data frame
mini_starwars <- starwars %>% tidyr::drop_na(mass) %>%
sample_n(size = 5) # getting 5 random values
pie_chart(
data = mini_starwars,
value = "mass",
label = "name"
)Using the padRadius, padAngle and
cornerRadius parameters, one can get fancier pie
charts:
pie_chart(
data = mini_starwars,
value = "mass",
label = "name",
padRadius = 200,
padAngle = 0.1,
cornerRadius = 50,
innerRadius = 10
)If you need a donut chart, you just need to play with the
innerRadius parameter:
pie_chart(
data = mini_starwars,
value = "mass",
label = "name",
innerRadius = 120,
cornerRadius = 20,
title = "5 Starwars characters ranked by their mass",
titleFontSize = 16,
bgcol = "yellow"
)
treemap_chart()
A treemap shows part-to-whole data as nested rectangles whose areas
are proportional to a value. Ben Shneiderman invented the technique in
the early 1990s. It became famous through SmartMoney’s “Map of the
Market” and the New York Times’ graphics of the US federal budget. Use
it when you have many parts (optionally grouped into categories) and
want to see at a glance which ones dominate the total. When you supply a
group column, tiles are coloured by group and each group
gets a header showing its total. Hover over a tile to see its value and
its share of the total.
budget <- data.frame(
department = c("Hospitals", "Primary care", "Public health",
"Schools", "Universities", "Vocational training",
"Army", "Navy", "Air force",
"Roads", "Railways", "Airports",
"Pensions", "Unemployment", "Family benefits"),
ministry = c("Health", "Health", "Health",
"Education", "Education", "Education",
"Defence", "Defence", "Defence",
"Transport", "Transport", "Transport",
"Social security", "Social security", "Social security"),
spending = c(5200, 2100, 800,
3900, 1800, 600,
2300, 1400, 1700,
1500, 1100, 400,
7400, 1900, 1300)
)
treemap_chart(
data = budget,
value = "spending",
label = "department",
group = "ministry",
valueFormat = "$,.0f",
title = "Where the money goes (millions)"
)Labels are truncated or hidden automatically when a tile is too small to fit them, so the chart stays readable even with many rectangles. In the example below, most of the 142 countries are too small to label, but you can hover over any tile to identify it.
library(gapminder)
pop_2007 <- gapminder[gapminder$year == 2007, ]
treemap_chart(
data = pop_2007,
value = "pop",
label = "country",
group = "continent",
valueFormat = ".3~s",
padding = 1,
title = "World population in 2007"
)
waffle_chart()
A waffle chart is a grid of squares, 10 x 10 by default, where each
category fills a number of cells in proportion to its share of the
whole. With 100 cells, each square reads as one percent, so “about a
third” or “fewer than one in ten” is visible at a glance. Readers find
this easier to judge than pie slices. Pew Research Center,
FiveThirtyEight, The Economist and the Washington Post use the format
often, and in R it was popularised by Bob Rudis’s waffle
package. Use it when a handful of categories make up a single whole,
such as survey responses, vote shares or budget splits. Cells are
allocated with the largest-remainder method, so the counts always add up
exactly to the number of cells. Hover over a cell or a legend entry to
highlight that category.
survey <- data.frame(
response = c("Strongly agree", "Agree", "Neutral",
"Disagree", "Strongly disagree"),
n = c(312, 405, 158, 87, 38)
)
waffle_chart(
data = survey,
category = "response",
value = "n",
colors = c("#1a9641", "#a6d96a", "#bdbdbd", "#fdae61", "#d7191c"),
title = "Do you support the new policy?"
)You can change the grid size with rows and
cols, and the fill order with
direction = "col". The example below shows each continent’s
share of the world population in 2007 on a 10 x 20 grid, where each cell
is half a percent:
library(gapminder)
pop_2007 <- gapminder[gapminder$year == 2007, ]
pop_continent <- aggregate(pop ~ continent, data = pop_2007, FUN = sum)
waffle_chart(
data = pop_continent,
category = "continent",
value = "pop",
direction = "col",
rows = 10,
cols = 20,
title = "World population by continent, 2007"
)
sunburst_chart()
sunburst_chart() draws hierarchical data as concentric
rings. It is inspired by the signature sunburst chart of Apache ECharts and reimplemented
in plain D3. Hover over a sector to highlight its branch, click it to
zoom in, and click the centre to zoom back out.
library(gapminder)
pop_2007 <- gapminder[gapminder$year == 2007, ]
sunburst_chart(
data = pop_2007,
levels = c("continent", "country"),
value = "pop",
valueFormat = ".3~s",
rootLabel = "World",
title = "World population in 2007"
)Without a value column, sectors are sized by row
counts:
sunburst_chart(
data = mpg,
levels = c("class", "manufacturer"),
rootLabel = "Cars",
labelRotate = "tangential",
title = "Number of car models by class and manufacturer"
)
mosaic_chart()
mosaic_chart() draws a mosaic (Marimekko) chart,
inspired by the mosaic example in the Vega-Lite gallery. Each
column’s width is that category’s share of the total, and each column is
split into segments that add up to 100%, so every cell’s area is
proportional to its count. Hover over a cell to see its count, its
column’s share and its share within the column.
titanic <- as.data.frame(Titanic)
mosaic_chart(
data = titanic,
x = "Class",
fill = "Survived",
value = "Freq",
colors = c("#e45756", "#4c78a8"),
xtitle = "Share of passengers and crew",
ytitle = "Share within class",
title = "Who survived the Titanic?"
)When value is omitted, rows are counted. Factor levels
set the order of the columns and segments:
cars <- mtcars
cars$cyl <- factor(cars$cyl, levels = c(8, 6, 4), labels = c("8 cyl", "6 cyl", "4 cyl"))
cars$gear <- factor(cars$gear, levels = c(3, 4, 5), labels = c("3 gears", "4 gears", "5 gears"))
mosaic_chart(cars, x = "cyl", fill = "gear", labelType = "both",
legendTitle = "Gears", title = "Motor Trend cars: gears by cylinders")
rose_chart()
rose_chart() draws a Nightingale rose, also called a
coxcomb or polar area chart. It is inspired by the polar-interval rose
chart of AntV G2. Every
category gets a wedge of the same angle, and the radius follows a
square-root scale so that each wedge’s area stays proportional to its
value. An optional group column stacks the wedges. The
example below uses Florence Nightingale’s own monthly death counts from
the Crimean War, 1854–55 (the same values as
HistData::Nightingale).
mon <- c("Apr 1854", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov",
"Dec", "Jan 1855", "Feb", "Mar")
crimea <- data.frame(
month = factor(rep(mon, times = 3), levels = mon),
cause = factor(rep(c("Preventable disease", "Wounds", "Other causes"), each = 12),
levels = c("Preventable disease", "Wounds", "Other causes")),
deaths = c(1, 12, 11, 359, 828, 788, 503, 844, 1725, 2761, 2120, 1205,
0, 0, 0, 0, 1, 81, 132, 287, 114, 83, 42, 32,
5, 9, 6, 23, 30, 70, 128, 106, 131, 324, 361, 172)
)
rose_chart(
data = crimea,
category = "month",
value = "deaths",
group = "cause",
colors = c("#7fa7c9", "#e0645c", "#4d4d4d"),
title = "Causes of death in the army in the East, 1854-55",
height = 560
)Use sort to order the wedges by size:
rose_chart(
data = data.frame(state = rownames(USArrests)[1:12],
murder = USArrests$Murder[1:12]),
category = "state",
value = "murder",
sort = "desc",
valueFormat = ".1f",
title = "Murder arrests per 100,000 residents (1973)"
)
parliament_chart()
You can easily create a parliament chart using the
parliament_chart() function, consider the following
example:
# The data is a toy example and does not reflect the reality
vote_results_germany <- data.frame(
political_party = c("SDP", "CDU", "Linke", "Grüne"),
number_of_seats = c(200, 40, 30, 20)
)
parliament_chart(
data = vote_results_germany,
categorical_column = "political_party",
numerical_column = "number_of_seats",
title = "German Bundestag",
seatSize = 10,
bgcol = "#fefefe"
)