Build donut/pie charts with 'ggplot2' layer by layer, exploiting the advantages of polar symmetry. Leverage layouts to distribute labels effectively. Connect labels to donut segments using pins. Streamline annotation and highlighting.

The Donutsk package allows you to build donut/pie charts with ggplot2 layer by layer, exploiting the advantages of polar symmetry. The package is designed to address the limitations of pie charts, which are well-known, while also capitalizing on their ability to effectively represent hierarchical data structures. The following features are worth to be highlighted:
packing() function arranges data to distribute small values
further apart from each otherglue::glue() for convenient label
construction like Total: {.sum}, where .sum is pre-calculated
variable.You can install the development version of donutsk from GitHub with:
# install.packages("devtools")
devtools::install_github("dkibalnikov/donutsk")
CRAN installation:
install.packages("donutsk")
Basic example:
library(donutsk)
#> Loading required package: ggplot2
# Create an example data set
n <- 40
set.seed(2021)
df <- dplyr::tibble(
lvl1 = sample(LETTERS[1:5], n, TRUE),
lvl2 = sample(LETTERS[6:24], n, TRUE),
value = sample(1:20, n, TRUE),
highlight_ext = sample(c(FALSE,TRUE), n, TRUE, c(.9, .1))) |>
dplyr::mutate(highlight_int = dplyr::if_else(lvl1 == "A",TRUE,FALSE))
# Doubled donut with advanced labeling
dplyr::group_by(df, lvl1, lvl2, highlight_ext, highlight_int) |>
dplyr::summarise(value = sum(value), .groups = "drop") |>
# Pack values effectively
packing(value, lvl1) |>
ggplot(aes(value = value, fill = lvl1)) +
# The donutsk visualization functions
geom_donut_int(aes(highlight = highlight_int), alpha=.5, r_int = .25) +
geom_label_int(aes(label = "Sum {fill}:\n{.sum} ({scales::percent(.prc)})"),
alpha = .6, col = "white", r=1.2) +
geom_donut_ext(aes(opacity = lvl2, highlight = highlight_ext)) +
geom_label_ext(aes(label = paste0(lvl2, ": {scales::percent(.prc_grp)}")),
show.legend = FALSE, col="white",
layout = tv(thinner = TRUE)) +
geom_pin(size=.5, linewidth=.1, show.legend = FALSE, cut = .25,
layout = tv(thinner = TRUE)) +
# Additional appearance settings
scale_fill_viridis_d(option = "inferno", begin = .1, end = .7) +
theme_void() +
theme(legend.position = "none") +
coord_polar(theta = "y")
There is a list of packages that can be considered as alternatives:
PieDonut()
function.ggpubr::ggpie() for
details.The following list of ideas is considered as a kind of roadmap: