Visualization VocabularyDataviz vocabulary
Diagram: onion diagram
Drawing: Adrien Taudière (CC0)
ggplot2 example: onion diagram
Adrien Taudière (CC0); R code ↓; data: gapminder (Bryan 2025) (CC BY 4.0)

chart

onion diagram

also: onion model

Set diagram of concentric circles in which each set lies strictly inside the one around it, from the most general to the most specific.

diagramme en oignon

Diagramme d'ensembles en cercles concentriques où chaque ensemble est strictement contenu dans celui qui l'entoure, du plus général au plus particulier.

Forme d'un diagramme d'Euler à ensembles emboîtés. Les couches ont une aire proportionnelle à leur effectif (eulerr) ou restent conceptuelles, comme dans les schémas de gestion ; à ne pas confondre avec le graphique en anneau ni le diagramme en rayons de soleil, qui découpent un tout en parts.

Classification

  • chart
  • sets › set diagrams
  • the name evokes: food

Channels

Attestation

  • French term: Common usage, not attested by a source

Scientific literature

OpenAlex: 25 papers since 2010, 28% in the last five years; mostly in Engineering, Business, Management and Accounting, Social Sciences; Wikidata

R packages

R code of the ggplot2 example

library(ggplot2)
library(dplyr)
library(ggforce)
library(gapminder)

## Four nested sets of countries in 2007, drawn as concentric circles whose
## areas are their populations: the data's 142 countries, their European
## countries, the European Union, the euro area.
## Membership on 1 January 2007: the EU had 27 members (Bulgaria and Romania
## joined that day), the euro area 13 (Slovenia joined that day). Gapminder
## lacks Cyprus, Estonia, Latvia, Lithuania, Luxembourg and Malta, about
## 9 million people: 21 EU members and 12 euro members remain.
eu <- c("Austria", "Belgium", "Bulgaria", "Czech Republic", "Denmark", "Finland",
        "France", "Germany", "Greece", "Hungary", "Ireland", "Italy", "Netherlands",
        "Poland", "Portugal", "Romania", "Slovak Republic", "Slovenia", "Spain",
        "Sweden", "United Kingdom")
euro <- c("Austria", "Belgium", "Finland", "France", "Germany", "Greece", "Ireland",
          "Italy", "Netherlands", "Portugal", "Slovenia", "Spain")
countries <- gapminder |>
  filter(year == 2007) |>
  mutate(pop = as.numeric(pop), country = as.character(country))
europe <- countries$country[countries$continent == "Europe"]
## Each set lies strictly inside the one around it.
stopifnot(all(euro %in% eu), all(eu %in% europe))

sets <- tibble(
  label = c("All 142 countries", paste(length(europe), "European countries"),
            "European Union, 21 of 27 members", "Euro area, 12 of 13 members"),
  pop = c(sum(countries$pop), sum(countries$pop[countries$country %in% europe]),
          sum(countries$pop[countries$country %in% eu]),
          sum(countries$pop[countries$country %in% euro]))
) |>
  mutate(r = sqrt(pop / 1e9 / pi),
         people = ifelse(pop >= 1e9, sprintf("%.2f billion people", pop / 1e9),
                         sprintf("%.0f million people", pop / 1e6)))
stopifnot(!is.unsorted(rev(sets$pop), strictly = TRUE))

## The three inner sets are named on the right, each by a segment that ends
## in the middle of its ring (or of the inner disc).
R <- sets$r[1]
inner <- sets[-1, ] |>
  mutate(r_mid = (r + c(r[-1], 0)) / 2,
         angle = c(40, 0, -40) * pi / 180,
         x = r_mid * cos(angle), y = r_mid * sin(angle),
         xend = R + 0.25, yend = c(0.75, 0, -0.75))

p <- ggplot() +
  geom_circle(data = sets, aes(x0 = 0, y0 = 0, r = r), colour = "#9b2367",
              fill = "#9b2367", alpha = 0.14, linewidth = 0.4) +
  annotate("text", x = 0, y = R * 0.68, size = 3, colour = "#535353", lineheight = 0.9,
           label = paste0(sets$label[1], "\n", sets$people[1])) +
  geom_segment(data = inner, aes(x = x, y = y, xend = xend, yend = yend),
               colour = "#535353", linewidth = 0.3) +
  geom_point(data = inner, aes(x = x, y = y), colour = "#535353", size = 0.6) +
  geom_text(data = inner, aes(x = xend + 0.06, y = yend, label = paste0(label, "\n", people)),
            hjust = 0, size = 2.8, colour = "#535353", lineheight = 0.9) +
  coord_equal(xlim = c(-R - 0.05, R + 2.6), clip = "off") +
  labs(title = "One person in twenty lived in the euro area in 2007",
       subtitle = "Population of the 142 countries in the data; areas drawn to scale",
       x = NULL, y = NULL,
       caption = "Data: Gapminder, via the gapminder R package; membership on 1 January 2007") +
  theme_lex_viz(grid = "", arrows = "") +
  theme(axis.text = element_blank())

Sources (1)

Cite this entry

Stable addresshttps://dataviz.adrientaudiere.com/en/term/onion-diagram.html

ReferenceTaudière Adrien. 2026. onion diagram. In Visualization Vocabulary, version 1.0.0. IdEst. https://dataviz.adrientaudiere.com/en/term/onion-diagram.html

BibTeX
@incollection{taudiere2026-onion-diagram,
  author    = {Taudière, Adrien},
  title     = {onion diagram},
  booktitle = {Visualization Vocabulary},
  year      = {2026},
  version   = {1.0.0},
  publisher = {IdEst},
  url       = {https://dataviz.adrientaudiere.com/en/term/onion-diagram.html},
  note      = {CC0 1.0}
}

Page created on 2026-11-09. Text last changed on 2026-11-12. Images last changed on 2026-11-11. Numbers computed on 2026-10-22.