rggplot2labelpercentagestacked-bar-chart

Problems in adding text to a stack bar chart in R


I'm trying to arrange my stacked bar chart with percentages displaying on each stack. I referred to the following, but I have doubts in 3 areas, which I cannot relate the code to my scenario. Adding labels to percentage stacked barplot ggplot2

Problem 1: The text annotated are not properly centered

Problem 2: I have equal percentage contribution to one instance, I need to arrange that in the order appearing in the legend from left to right (I have achieved this already). For the rest of the cases, I need to arrange the stacks in contribution order (sorted by Contribution)

Problem 3: There are 0% contributions in some cases. I do not want to display 0%

Please see the code and the image attached to get some idea about the current stage of the code:

dput(df)
structure(list(QT = c("BMI", "BMI", "BMI", "BMI", "BMI", "WHR", 
"WHR", "WHR", "WHR", "WHR", "BF", "BF", "BF", "BF", "BF", "WC", 
"WC", "WC", "WC", "WC"), E = c("HD", "NS", "PA", "PALC", "SMK", 
"HD", "NS", "PA", "PALC", "SMK", "HD", "NS", "PA", "PALC", "SMK", 
"HD", "NS", "PA", "PALC", "SMK"), Contribution = c(21.73913043, 
0, 21.73913043, 34.7826087, 21.73913043, 24.13793103, 24.13793103, 
20.68965517, 13.79310345, 17.24137931, 16.66666667, 16.66666667, 
20, 20, 26.66666667, 20, 20, 20, 20, 20)), row.names = c(NA, 
20L), class = "data.frame")

library(ggplot2)

ggplot(df, aes(x = Contribution, y = QT,  fill = E)) +
  geom_col(size=0.5, color="black", 
           position = position_fill(reverse = TRUE)) +
  scale_fill_brewer(palette = "Set2") +
  theme_minimal()+
  theme(axis.text=element_text(size=12, colour = "black"),
        axis.title = element_text(size=13),
        axis.text.x = element_blank(),
         legend.text = element_text(size=12))+
  geom_text(aes(label = paste0(round(Contribution), "%")),
            position = position_fill(vjust = 0.5))

image attached


Solution

  • As you reversed the order of your bars using reverse=TRUE you have to do the same for the labels to align them with the bars.

    To get rid of the labels for the zeros you could use an ifelse.

    Finally, to order each stack according to Contribution you could use a helper column which I create by rearranging your data and using forcats::fct_inorder. This helper column could then be mapped on the group aes.

    library(ggplot2)
    library(dplyr, warn = FALSE)
    
    
    df |> 
      arrange(QT, desc(Contribution)) |> 
      mutate(
        group = forcats::fct_inorder(paste(QT, E, sep = "."))
      ) |> 
      ggplot(aes(x = Contribution, y = QT, fill = E, group = group)) +
      geom_col(
        size = 0.5, color = "black",
        position = position_fill(reverse = TRUE)
      ) +
      scale_fill_brewer(palette = "Set2") +
      theme_minimal() +
      theme(
        axis.text = element_text(size = 12, colour = "black"),
        axis.title = element_text(size = 13),
        axis.text.x = element_blank(),
        legend.text = element_text(size = 12)
      ) +
      geom_text(
        aes(label = ifelse(
          Contribution > 0,
          paste0(round(Contribution), "%"),
          ""
        )),
        position = position_fill(vjust = 0.5, reverse = TRUE)
      )
    

    enter image description here