Waffle charts for visualizing proportions

Application exercise
Create and customize waffle charts using the {waffle} package in R.
Modified

May 24, 2026

ImportantGetting started

This application exercise is designed to be run in your web browser using the {webr} framework. Simply work through the exercises and use the provided code cells to execute live R code in your browser.

Waffle charts

{waffle} provides a {ggplot2} implementation of waffle plots. The typical workflow consists of preparing the data by tabulating in advance and then plotting it with {ggplot2} and geom_waffle().

Basic waffle chart

Demonstration: Prepare the penguins data frame to visualize the number of penguins by species.

penguins |>
  count(species)
    species   n
1    Adelie 152
2 Chinstrap  68
3    Gentoo 124

Demonstration: Use the prepared data to draw a basic color-coded waffle chart.

penguins |>
  count(species) |>
  ggplot(mapping = aes(fill = species, values = n)) +
  geom_waffle() +
  labs(
    title = "Penguins by species",
    x = NULL,
    y = NULL,
    fill = NULL
  )

Improve the waffle chart

Your turn: Adjust the waffle chart to use a fixed aspect ratio so the symbols are squares. Rotate the chart so the squares are stacked vertically.

TipSuggested solution
penguins |>
  count(species) |>
  ggplot(mapping = aes(fill = species, values = n)) +
  geom_waffle(
    n_rows = 20,
    size = 1,
    color = "white",
    flip = TRUE
  ) +
  labs(
    title = "Penguins by species",
    x = NULL,
    y = NULL,
    fill = NULL
  ) +
  coord_cartesian(ratio = 1)

Demonstration: {waffle} will draw all observations on the chart. For larger datasets, this is problematic. Instead, we might want to visualize the proportion of observations in each category. Use geom_waffle() to represent the data as proportions instead.

penguins |>
  count(species) |>
  ggplot(mapping = aes(fill = species, values = n)) +
  geom_waffle(
    size = 1,
    color = "white",
    make_proportional = TRUE
  ) +
  labs(
    title = "Penguins by species",
    x = NULL,
    y = NULL,
    fill = NULL
  ) +
  coord_cartesian(ratio = 1)

Your turn: Adjust the waffle chart to use a better color palette and move the legend to the top.

TipSuggested solution
penguins |>
  count(species) |>
  ggplot(mapping = aes(fill = species, values = n)) +
  geom_waffle(
    size = 1,
    color = "white",
    make_proportional = TRUE
  ) +
  scale_fill_viridis_d(end = 0.8) +
  labs(
    title = "Penguins by species",
    x = NULL,
    y = NULL,
    fill = NULL
  ) +
  coord_cartesian(ratio = 1) +
  theme(legend.position = "top")

Compare to a pie chart

Demonstration: Create a pie chart and a donut chart to visualize the proportions of penguins by species.

# pie chart
penguins |>
  count(species) |>
  ggplot(mapping = aes(x = "", y = n, fill = species)) +
  geom_col(color = "white") +
  coord_radial(theta = "y", expand = FALSE) +
  scale_fill_viridis_d(end = 0.8) +
  labs(
    title = "Penguins by species",
    x = NULL,
    y = NULL,
    fill = NULL
  ) +
  theme_void() +
  theme(legend.position = "top")

# donut chart
penguins |>
  count(species) |>
  ggplot(mapping = aes(x = 2, y = n, fill = species)) +
  geom_col(color = "white") +
  coord_radial(theta = "y", expand = FALSE) +
  xlim(0.5, 2.5) +
  scale_fill_viridis_d(end = 0.8) +
  labs(
    title = "Penguins by species",
    x = NULL,
    y = NULL,
    fill = NULL
  ) +
  theme_void() +
  theme(legend.position = "top")

Your turn: Reflect on the differences between waffle charts and pie/donut charts. For this data, which chart type do you find more effective? Why?

sessioninfo::session_info()
─ Session info ───────────────────────────────────────────────────────────────
 setting  value
 version  R version 4.5.2 (2025-10-31)
 os       macOS Tahoe 26.5
 system   aarch64, darwin20
 ui       X11
 language (EN)
 collate  en_US.UTF-8
 ctype    en_US.UTF-8
 tz       America/New_York
 date     2026-05-24
 pandoc   3.8.3 @ /Applications/Positron.app/Contents/Resources/app/quarto/bin/tools/aarch64/ (via rmarkdown)
 quarto   1.10.3 @ /Applications/quarto/bin/quarto

─ Packages ───────────────────────────────────────────────────────────────────
 ! package      * version   date (UTC) lib source
 P cli            3.6.6     2026-04-09 [?] RSPM
 P curl           7.1.0     2026-04-22 [?] RSPM
 P digest         0.6.39    2025-11-19 [?] RSPM (R 4.5.0)
 P dplyr        * 1.2.1     2026-04-03 [?] RSPM
 P DT             0.34.0    2025-09-02 [?] RSPM
 P evaluate       1.0.5     2025-08-27 [?] RSPM (R 4.5.0)
 P extrafont      0.20      2025-09-24 [?] RSPM
 P extrafontdb    1.1       2025-09-28 [?] RSPM
 P farver         2.1.2     2024-05-13 [?] RSPM (R 4.5.0)
 P fastmap        1.2.0     2024-05-15 [?] RSPM (R 4.5.0)
 P forcats      * 1.0.1     2025-09-25 [?] RSPM (R 4.5.0)
 P generics       0.1.4     2025-05-09 [?] RSPM (R 4.5.0)
 P ggplot2      * 4.0.3     2026-04-22 [?] RSPM
 P glue           1.8.1     2026-04-17 [?] RSPM
 P gridExtra      2.3       2017-09-09 [?] RSPM (R 4.5.0)
 P gtable         0.3.6     2024-10-25 [?] RSPM (R 4.5.0)
 P here           1.0.2     2025-09-15 [?] CRAN (R 4.5.0)
 P hms            1.1.4     2025-10-17 [?] RSPM (R 4.5.0)
 P htmltools      0.5.9     2025-12-04 [?] RSPM (R 4.5.0)
 P htmlwidgets    1.6.4     2023-12-06 [?] RSPM (R 4.5.0)
 P jsonlite       2.0.0     2025-03-27 [?] RSPM (R 4.5.0)
 P knitr          1.51      2025-12-20 [?] RSPM (R 4.5.0)
 P labeling       0.4.3     2023-08-29 [?] RSPM (R 4.5.0)
 P lifecycle      1.0.5     2026-01-08 [?] RSPM (R 4.5.0)
 P lubridate    * 1.9.5     2026-02-04 [?] RSPM
 P magrittr       2.0.5     2026-04-04 [?] RSPM
 P otel           0.2.0     2025-08-29 [?] RSPM (R 4.5.0)
 P pillar         1.11.1    2025-09-17 [?] RSPM (R 4.5.0)
 P pkgconfig      2.0.3     2019-09-22 [?] RSPM (R 4.5.0)
 P plyr           1.8.9     2023-10-02 [?] RSPM (R 4.5.0)
 P purrr        * 1.2.2     2026-04-10 [?] RSPM
 P R6             2.6.1     2025-02-15 [?] RSPM (R 4.5.0)
 P RColorBrewer   1.1-3     2022-04-03 [?] RSPM (R 4.5.0)
 P Rcpp           1.1.1-1.1 2026-04-24 [?] RSPM
 P readr        * 2.2.0     2026-02-19 [?] RSPM
 P renv           1.2.3     2026-05-16 [?] RSPM
 P rlang          1.2.0     2026-04-06 [?] RSPM
 P rmarkdown      2.31      2026-03-26 [?] RSPM
 P rprojroot      2.1.1     2025-08-26 [?] RSPM (R 4.5.0)
 P Rttf2pt1       1.3.14    2025-09-26 [?] RSPM
 P S7             0.2.2     2026-04-22 [?] RSPM
 P scales         1.4.0     2025-04-24 [?] RSPM (R 4.5.0)
 P sessioninfo    1.2.3     2025-02-05 [?] RSPM (R 4.5.0)
 P stringi        1.8.7     2025-03-27 [?] RSPM (R 4.5.0)
 P stringr      * 1.6.0     2025-11-04 [?] RSPM (R 4.5.0)
 P tibble       * 3.3.1     2026-01-11 [?] RSPM (R 4.5.0)
 P tidyr        * 1.3.2     2025-12-19 [?] RSPM (R 4.5.0)
 P tidyselect     1.2.1     2024-03-11 [?] RSPM (R 4.5.0)
 P tidyverse    * 2.0.0     2023-02-22 [?] RSPM (R 4.5.0)
 P timechange     0.4.0     2026-01-29 [?] RSPM
 P tzdb           0.5.0     2025-03-15 [?] RSPM (R 4.5.0)
 P vctrs          0.7.3     2026-04-11 [?] RSPM
 P viridis      * 0.6.5     2024-01-29 [?] RSPM (R 4.5.0)
 P viridisLite  * 0.4.3     2026-02-04 [?] CRAN (R 4.5.2)
 P waffle       * 1.0.2     2026-01-05 [?] Github (hrbrmstr/waffle@767875b)
 P withr          3.0.2     2024-10-28 [?] RSPM (R 4.5.0)
 P xfun           0.57      2026-03-20 [?] RSPM
 P yaml           2.3.12    2025-12-10 [?] RSPM (R 4.5.0)

 [1] /Users/bcs88/Projects/info-3312/course-site/renv/library/macos/R-4.5/aarch64-apple-darwin20
 [2] /Users/bcs88/Library/Caches/org.R-project.R/R/renv/sandbox/macos/R-4.5/aarch64-apple-darwin20/4cd76b74

 * ── Packages attached to the search path.
 P ── Loaded and on-disk path mismatch.

──────────────────────────────────────────────────────────────────────────────