Search code examples
rggplot2geom-textstacked-bar-chart

Adding in text (from a column) to stacked bar chart ggplot in R


Here is my sample dataset and I would like to make a stacked barchart.

dat <- data.frame(practice =c("walk in", "ltc", "emerg", "specialty"),
                   in_person=c(2463,987,3029,1200),
                  virtual = c(233,278,109,409),
                   percent_of_virtual =  c(8.6, 22, 3.5,25.4))

dat1 <-dat[c(1,2,3)]

dat1 <- dat1 %>%
  tidyr::pivot_longer(cols=-c(practice), names_to = "visit", values_to = "Number")

ggplot(dat1, aes(x = practice, y = Number, fill = visit)) +
  geom_col(position=position_stack(reverse = TRUE)) + coord_flip()

Using the above code I get the following stacked chart. This is what I want but I would like to add in the variable "percent_of_virtual" from "dat" as text at the outside of each bar.

enter image description here

I need the output to look something like the below. As you see here for each practice the % of virtual visits (calculated as virtual visit/virtual visit+in_person visit) is added as text. I tried doing this with geom_text but was unsuccessful. I would like to find a method without manually having to add the text in because I have to do this for multiple graphs. Any help would be appreciated!!

enter image description here


Solution

  • You need to use position_stack on the text. I would probably change your data shaping to include the percentage column, but conditionally mask it for the in person group:

    dat %>%
      tidyr::pivot_longer(2:3, names_to = "visit", values_to = "Number") %>%
      ggplot(aes(x = practice, y = Number, fill = visit)) +
      geom_col(position = position_stack(reverse = TRUE), width = 0.5) + 
      geom_text(aes(label = ifelse(visit == "virtual", 
                                   paste0(percent_of_virtual, "%"), "")),
                position = position_stack(vjust = 1, reverse = TRUE),
                hjust = -0.5, size = 6) +
      ylim(c(0, 4000)) +
      scale_fill_manual(values = c("gray50", "orange")) +
      coord_flip() +
      theme_minimal(base_size = 20)
    

    enter image description here