Search code examples
rggplot2levelsdonut-chart

Donut chart with 3 levels in R


trying to replicate the donut chart in the following post (first answer: Multiple, dependent-level sunburst/doughnut chart using ggplot2) looking for a solution with a donut chart that looks more or less like that: enter image description here How would I need to adapt the following code to get such a plot:

df <- "name  type    value
Total   all     100
Planerlöse   Total 54
Total   all   100
Abgeltung   Thurgau   30.24
Abgeltung   Bund     23.8
Abgeltung   Kanton Thurgau Netto   20.23
Abgeltung   Gemeinden   9.98" %>% read_table2() %>%
  filter(type != "all") %>%
  mutate(name = as.factor(name) %>% fct_reorder(value, sum)) %>%
  arrange(name, value) %>%
  mutate(type = as.factor(type) %>% fct_reorder2(name, value))

lvl0 <- tibble(name = "Parent", value = 0, level = 0, fill = NA)

lvl1 <- df %>%
  group_by(name) %>%
  summarise(value = sum(value)) %>%
  ungroup() %>%
  mutate(level = 1) %>%
  mutate(fill = name)

lvl2 <- df %>%
  select(name = type, value, fill = name) %>%
  mutate(level = 2)


lvl3 <- df %>%
  select(name = type, value, fill = name) %>%
  mutate(level = 3)


bind_rows(lvl0, lvl1, lvl2, lvl3) %>%
  mutate(name = as.factor(name) %>% fct_reorder2(fill, value)) %>%
  arrange(fill, name) %>%
  mutate(level = as.factor(level)) %>%
  ggplot(aes(x = level, y = value, fill = fill, alpha = level)) +
  geom_col(width = 1, color = "gray90", size = 0.25, position = position_stack()) +
  geom_text(aes(label = name), size = 2.5, position = position_stack(vjust = 0.5)) +
  coord_polar(theta = "y") +
  scale_alpha_manual(values = c("0" = 0, "1" = 1, "2" = 0.7, "3"=0.4), guide = F) +
  scale_x_discrete(breaks = NULL) +
  scale_y_continuous(breaks = NULL) +
  scale_fill_brewer(palette = "Dark2", na.translate = F) +
  labs(x = NULL, y = NULL) +
  theme_minimal()

Thank you for any help!


Solution

  • Here's a simplified version of the code you posted, which generates a three layered donut chart:

    df <- read.table(text="name  type    value
    Planerlöse   Total 54
    Abgeltung   Thurgau   30.24
    Abgeltung   Bund     23.8
    Abgeltung   'Kanton Thurgau Netto'   20.23
    Abgeltung   Gemeinden   9.98", header=T)
    
    lvl0 <- tibble(name = "Parent", value = 0, level = 0, fill = NA)
    
    lvl1 <- df %>%
      group_by(name) %>%
      summarise(value = sum(value)) %>%
      ungroup() %>%
      mutate(level = 1, 
             fill = name)
    
    lvl2 <- df %>%
      select(name = type, value, fill = name) %>%
      mutate(level = 2)
    
    
    lvl3 <- df %>%
      select(name = type, value, fill = name) %>%
      mutate(level = 3)
    
    
    bind_rows(lvl0, lvl1, lvl2, lvl3) %>%
      mutate(fill = ifelse(is.na(fill), "Total", fill),
             name = as.factor(name),
             level = as.factor(level)) %>%
      arrange(fill, name) %>%
      ggplot(aes(x = level, y = value, fill = fill, alpha = level)) +
      geom_col(width = 1, color = "gray90", size = 0.25, position = position_stack()) +
      geom_text(aes(label = name), size = 2.5, position = position_stack(vjust = 0.5)) +
      coord_polar(theta = "y") +
      scale_alpha_manual(values = c("0" = 0, "1" = 1, "2" = 0.7, "3"=0.4), guide = F) +
      scale_x_discrete(breaks = NULL) +
      scale_y_continuous(breaks = NULL) +
      scale_fill_brewer(palette = "Dark2", na.translate = F) +
      labs(x = NULL, y = NULL) +
      theme_minimal()
    

    donuts