Search code examples
rggplot2bar-chartfacet-grid

how to show 'total' in faceted ggplot for filled bar with % label?


I have a filled bar chart like this

library(dplyr)
library(ggplot2)

df <- data.frame(facet=c(rep(1,6),rep(2,6)),type=rep(c('a','b','c'),2), subtype=c('x','y'), value=c(10,20,30,10,50,70))

df %>% group_by(type, facet) %>% 
mutate(pct=value/sum(value)) %>%
mutate(pos=cumsum(pct) - (0.5 * pct)) %>%
ggplot(aes(type, pct, fill=subtype)) + geom_bar(stat='identity') +
geom_text(aes(label=paste0(round(100*pct, 0), '%'),y=pos)) +   facet_grid(.~facet, margins=TRUE)

If without showing total in faceting it works. But due to the method used to show % data label (i wonder if there is a better way), the total facet gets messed up. any advice? thanks.


Solution

  • I arranged the labels properly and defined the margin plot beforehand. I guess this is the output you expected. I could not figure out if there is a way to achieve this with facet_grid(., margin = TRUE).

    df <- data.frame(facet=c(rep(1,6),rep(2,6)),type=rep(c('a','b','c'),2),
                     subtype=c('x','y'), value=runif(12, 0, 100))
    
    df1  <- df %>% 
            arrange(desc(subtype)) %>% 
            mutate(facet = factor(facet, levels = c("1", "2", "(all)"))) %>%
            group_by(type, facet) %>% 
            mutate(pct=value/sum(value),
                   pos=cumsum(pct) - (0.5 * pct)) 
    
    df2 <- df1 %>%
          group_by(type, subtype) %>%
          summarise(facet = factor("(all)", levels = c("1", "2", "(all)")),
                    pct = sum(pct)/2,
                    pos = sum(pos/2))  
    
      bind_rows(df1, df2) %>%
      ggplot(aes(type, pct, fill=subtype)) + 
      geom_bar(stat='identity', position = "stack") +
      geom_text(aes(label=paste0(round(100*pct, 0), '%'),y=pos)) +   
      facet_grid(.~facet)
    

    enter image description here