Search code examples
rggplot2bar-chartstacked

R ggplot2: Highlight Values in Stacked Barplot


I have a small dataframe called Participants10 (from dput()):

structure(list(AUC_numeric = c(0.59, 0.68, 0.57, 0.59, 0.74, 
0.53, 0.63, 0.59, 0.62, 0.51, 0.78, 0.55, 0.5, 0.5, 0.61), AUC_Factor = structure(c(3L, 
2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L), .Label = c("aEMA", 
"pEMA", "fEMA"), class = "factor"), ParticipantNr = c(1L, 1L, 
1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L, 5L, 5L, 5L), lab_ypos = c(0.295, 
0.93, 1.555, 0.295, 0.96, 1.595, 0.315, 0.925, 1.53, 0.255, 0.9, 
1.565, 0.25, 0.75, 1.305)), class = c("grouped_df", "tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -15L), groups = structure(list(
    ParticipantNr = 1:5, .rows = list(1:3, 4:6, 7:9, 10:12, 13:15)), row.names = c(NA, 
-5L), class = c("tbl_df", "tbl", "data.frame"), .drop = TRUE))

With ggplot I want to create a stacked bar plot like this:

ggplot(data = Participants10, aes(x = ParticipantNr, y = AUC_numeric))+
  geom_col(aes(fill = factor(AUC_Factor), width = 0.5)) +
  geom_text(aes(y = lab_ypos, label = AUC_numeric, group = factor(AUC_Factor) ), color = "white", parse = T)+
  theme(legend.title = element_blank(), 
        panel.background = element_blank(),
        panel.grid = element_blank()) +
  coord_flip()

How can I highlight (for example with color or with bold text or with sourrounding edges the highest value in the stacked bar for each ParticipantNR?


Solution

  • One approach is to precompute the group to highlight. I'll use dplyr:

    Here, we set highlight to "yes" when it is the maximum value for each ParticipantNr. Then we can use scale_color_manual to change the text color based on the highlight variable.

    library(dplyr)
    library(ggplot2)
    Participants10 %>%
      group_by(ParticipantNr) %>%
      mutate(highligth = case_when(AUC_numeric == max(AUC_numeric) ~ "yes", 
                                   TRUE ~ "no")) %>%
    ggplot(aes(x = ParticipantNr, y = AUC_numeric)) +
      geom_col(aes(fill = factor(AUC_Factor), color = highligth),
               width = 0.5) +
      geom_text(aes(y = lab_ypos, label = AUC_numeric,
                    group = factor(AUC_Factor),color = highligth )) +
      scale_color_manual(values = c("no" = "white", "yes" = "black"), guide = FALSE) + 
      theme(legend.title = element_blank(), 
            panel.background = element_blank(),
            panel.grid = element_blank()) +
      coord_flip()
    

    enter image description here

    Unfortunately, the outline option doesn't really look great because of clipping between bar regions.

    Participants10 %>%
      group_by(ParticipantNr) %>%
      mutate(highligth = case_when(AUC_numeric == max(AUC_numeric) ~ "yes", 
                                   TRUE ~ "no")) %>%
    ggplot(aes(x = ParticipantNr, y = AUC_numeric)) +
      geom_col(aes(fill = factor(AUC_Factor), color = highligth), width = 0.5) +
      geom_text(aes(y = lab_ypos, label = AUC_numeric, group = factor(AUC_Factor),color = highligth ), parse = T) +
      scale_color_manual(values = c("no" = "white", "yes" = "black"), guide = FALSE) + 
      theme(legend.title = element_blank(), 
            panel.background = element_blank(),
            panel.grid = element_blank()) +
      coord_flip()
    

    enter image description here