How to create a ggplot2 pie and donut chart on same plot?

Here is a start on a possible solution. I do not know how to get the text labels written radially. Also, shorter labels are probably needed.

library(dplyr)
#> Warning: package 'dplyr' was built under R version 3.5.3
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(tibble)
#> Warning: package 'tibble' was built under R version 3.5.3
library(tidyr)
#> Warning: package 'tidyr' was built under R version 3.5.3
library(ggplot2)
#> Warning: package 'ggplot2' was built under R version 3.5.3
metadata <- data.frame(tibble::tribble(
  ~Domain,  ~Total,                    ~Group,    ~Share,
  "Eukaryotes PR2", 2138457,               "Algae PR2", "1320398",
  "Bacteria Silva 16S", 2594766, "Cyanobacteria Silva 16S", "1524609",
  "Eukaryotes Silva 18S", 1237100,         "Algae Silva 18S",  "796201",
  "Archaea NCBI",   8e+05,                 "Nogroup", "Nogroup"
)
)

#Make Share numeric
metadata <- mutate(metadata, Share = ifelse(Share == "Nogroup", "0", Share)) %>% 
  mutate(Share = as.numeric(Share))

#Calculate the size and invent Group labels for the unnamed fraction of each Domain
metadata2 <- data.frame(Domain = metadata$Domain,
                        Total = metadata$Total,
                        Group = paste("Not", metadata$Group),
                        Share = metadata$Total - metadata$Share,
                        stringsAsFactors = FALSE)

#Make a data set where each Group is explicit
metadata2 <- rbind(metadata2, metadata) %>% 
  filter(Share != 0) %>% 
  mutate(Group = ifelse(Group == "Not Nogroup", Domain, Group)) %>%
  arrange(Domain, Group) 

metadata2 <- metadata2 %>%
  mutate(Tot = sum(Share)) %>% 
  group_by(Domain) %>% 
  mutate(CUM = cumsum(Share), DomSize = max(CUM))

#Calculate the bottom edge of the Domains when stacked
DomBot <- unique(select(metadata2, Domain, Tot, DomSize)) %>% ungroup() %>% 
  mutate(Bottom = Tot - cumsum(DomSize))

metadata2 <- inner_join(metadata2, select(DomBot, Domain, Bottom))
#> Joining, by = "Domain"
metadata2 <- mutate(metadata2, Pos = Bottom + CUM - Share/2)


plt <- ggplot() + geom_col(aes(x = 2, y = Total, fill = Domain), 
                    data = metadata, color = "black") + 
  geom_col(aes(x = 3, y = Share, fill = Domain), 
           data = metadata2, color = "black") +
  geom_text(aes(label = Group, x= 3, y = Pos), data = metadata2, size = 3)+
  xlim(0, 3.5) + labs(x = NULL, y = NULL) + 
  theme(axis.ticks=element_blank(),
axis.text=element_blank(),
axis.title=element_blank())

plt


plt + coord_polar(theta = "y") 

Created on 2019-10-22 by the reprex package (v0.3.0.9000)

3 Likes