Home > other >  3 layer donut chart in R
3 layer donut chart in R

Time:08-12

I am trying to recreate this image in R, however I am unable to work out how to have 3 layers to a donut chart - everything I find (for instance, webr::PieDonut) only allows 2. Using ggplot I am also unable to re-create it.

enter image description here

A MRE is:

library(ggplot2)
library(webr)
library(dplyr)

lexicon <- data.frame("Level1" = c(rep("Flavour", 11), rep("Appearance", 4)),
                  "Level2" = c(rep("Misc", 6), rep("Pungent", 5), rep("Colour", 4)),
                  "Level3" = c("Fresh", "Refreshing", "Soapy", "Minty", "Nutty", "Milky", "Peppery", "Sharp", "Horseradish", "Mustard hot", "Spicy", "Colourful"," Fresh Green", "Dark Green", "Bright Green")
)

PieDonut(lexicon, aes(Level1, Level2), title = "Salad Lexicon", showRatioDonut =FALSE, showRatioPie = FALSE)

ggplot(lexicon, aes(Level2, Level3, fill = Level1))  
  geom_col()  
  scale_fill_viridis_d()  
  coord_polar("y")

While the PieDonut works for 2 levels (not shown), it doesn't allow the final level to be included. The ggplot approach also does not work, as seen in the figure below.

enter image description here

How can I get this style of chart in R? Either with ggplot or base plotting.

CodePudding user response:

I think a nice alternative is to use geom_rect here after some data manipulation. Using the fill, color, and alpha scales can help improve the differentiation of categories. I would also use geom_textpath here, though I might go for circumferential labels if there is room to do so:

lexicon %>%
  mutate(top_level = Level1) %>%
  pivot_longer(1:3) %>%
  group_by(name, value) %>%
  mutate(width = n()) %>%
  unique() %>%
  arrange(name) %>%
  group_by(name) %>%
  mutate(ymid = as.numeric(sub("\\D ", "", name)),
         ymax = ymid   0.5, ymin = ymid - 0.5,
         xmin = c(0, head(cumsum(width), -1)),
         xmax = cumsum(width),
         xmid = (xmax   xmin) / 2) %>%
  ggplot(aes(xmid, ymid, fill = top_level))  
  geom_rect(aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax,
                alpha = name, color = top_level))  
  geomtextpath::geom_textpath(aes(y = ymid   0.25, label = value, 
                                  group = value))  
  scale_alpha_manual(values = c(1, 0.3, 0.1))  
  scale_fill_manual(values = c("#cd9900", "#00817e"))  
  scale_colour_manual(values = c("#cd9900", "#00817e"))  
  scale_y_continuous(limits = c(-0.5, 3.6))  
  coord_polar()  
  theme_void()  
  theme(legend.position = "none")

enter image description here

  • Related