Search code examples
rggplot2bar-chart

How to create a stacked bar chart with a totals column and labels of percentages for all the bars with ggplot2?


I am trying to produce a stacked bar chart with a column of totals and labels of percentages in each bar. But somehow I only manage to do either one or the other. Any help towards getting both things simultaneously would be very appreciated.

here goes an excerpt of my farm_size1 database:

structure(list(SPTOT = c(2L, 6L, 5L, 5L, 4L, 4L, 4L, 3L, 2L, 
2L, 2L, 3L, 4L, 2L, 5L, 2L, 3L, 4L, 4L, 4L), CASE = c(1L, 1L, 
1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L), case1 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), levels = c("1", 
"2", "3", "4"), class = "factor"), case2 = structure(c(1L, 1L, 
1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L), levels = c("Bierge", "Santa Creu", "Collbató", "Monells"
), class = "factor"), sptot1 = structure(c(2L, 6L, 5L, 5L, 4L, 
4L, 4L, 3L, 2L, 2L, 2L, 3L, 4L, 2L, 5L, 2L, 3L, 4L, 4L, 4L), levels = c("1", 
"2", "3", "4", "5", "6"), class = "factor"), sptot2 = c("50-100 Ha", 
"> 500 Ha", "> 500 Ha", "> 500 Ha", "201-500 Ha", "201-500 Ha", 
"201-500 Ha", "101-200 Ha", "50-100 Ha", "50-100 Ha", "50-100 Ha", 
"101-200 Ha", "201-500 Ha", "50-100 Ha", "> 500 Ha", "50-100 Ha", 
"101-200 Ha", "201-500 Ha", "201-500 Ha", "201-500 Ha")), row.names = c(NA, 
20L), class = "data.frame")

And this is the code I used to produce the proportional stacked bart chart with a column for totals:

farm_size1 %>%
  ggplot(aes(x=case2)) +
  geom_bar(aes(fill=sptot2), position="fill")+
  geom_bar(aes(x="Total", fill=sptot2), position= "fill")+
  scale_y_continuous(expand = c(0,0), labels = c("0", "25", "50", "75", "100"))+
  scale_fill_manual(values=c("#FB8072","#FBB4AE","#FDB462", "#2a7dad","#8DD3C7","#E6F5C9"),
                    labels=c("< 50 Ha", "50-100 Ha", "101-200 Ha", "201-500 Ha", "> 500 Ha"))+
  labs(x= "", y="Percentage", fill= "Farm size")

And this looks like this:

stacked bar chart with totals' column

And the code for producing the percentage labels is this:

farm_size1 %>%
  count(case2, sptot2)%>%
  group_by(case2)%>%
  mutate(pct=prop.table(n)*100)%>%
  ggplot()+
  aes(case2, pct, fill=sptot2)+
  geom_bar(stat = "identity")+
  ylab("Percentage of farms") +
  geom_text(aes(label=paste0(sprintf("%1.1f", pct),"%")),
            position=position_stack(vjust=0.5), size=3)+
  scale_fill_manual(values=c("#FB8072","#FBB4AE","#FDB462", "#2a7dad","#8DD3C7","#E6F5C9"),
                    labels=c("< 50 Ha", "50-100 Ha", "101-200 Ha", "201-500 Ha", "> 500 Ha"))

And I produced the following graph: stacked bar chart with labels


Solution

  • You can add new data to your data frame making so that every case2 is equal "Total"

    farm_size1 %>%
      #new code
      bind_rows(farm_size1 %>% mutate(case2 = "Total")) %>% 
      #########
      count(case2, sptot2)%>%
      group_by(case2)%>%
      mutate(pct=prop.table(n)*100)%>%
      ggplot()+
      aes(case2, pct, fill=sptot2)+
      geom_bar(stat = "identity")+
      ylab("Percentage of farms") +
      geom_text(aes(label=paste0(sprintf("%1.1f", pct),"%")),
                position=position_stack(vjust=0.5), size=3)+
      scale_fill_manual(values=c("#FB8072","#FBB4AE","#FDB462", "#2a7dad","#8DD3C7","#E6F5C9"),
                        labels=c("< 50 Ha", "50-100 Ha", "101-200 Ha", "201-500 Ha", "> 500 Ha"))
    

    enter image description here