Positioning data labels on a grouped bar chart (ggplot)

I am very new to R, so hopefully my question makes sense. As you can see, the data labels for my grouped bars overlap. I've used position = position_dodge(.8) to place my errorbars but I can't seem to find a way to do the same for my data labels.

Thanks in advance for any help.

subDF %>% 
  ggplot(aes(fill= Order, y= Score, x=FSM)) + 
  facet_wrap(~Group, scale = "fixed")+
  stat_summary(fun ="mean", geom="bar", position="dodge")+
  stat_summary(geom = "errorbar", fun.data = mean_cl_boot, position = position_dodge(.8), size=.3, width =.5)+
  ylim(0,10)+
  ylab("Mean PACIER score")+
  geom_label(inherit.aes = FALSE, data = . %>%
               group_by(FSM,Order, Group) %>%
               count(),aes(label = paste0(n, " Obs."), x = FSM), y = 0.5)

Welcome to R and to the Rstudio community!

The problem does make sense, and it's one I remember encountering when I started out with ggplot a year ago. I didn't remember the solution, so after some Google searches, I pulled up the help page for position_dodge. It says this (emphasis added):

Dodging preserves the vertical position of an geom while adjusting the horizontal position. position_dodge2 is a special case of position_dodge for arranging box plots, which can have variable widths. position_dodge2 also works with bars and rectangles. But unlike position_dodge , position_dodge2 works without a grouping variable in a layer.

That seemed like a good thing to try, so I added in position_dodge2 to the geom_label call (commented below). It seems to work!

subDF %>% 
  ggplot(aes(fill= Order, y= Score, x=FSM)) + 
  facet_wrap(~Group, scale = "fixed")+
  stat_summary(fun ="mean", geom="bar", position="dodge")+
  stat_summary(geom = "errorbar", fun.data = mean_cl_boot, position = position_dodge(.8), size=.3, width =.5)+
  ylim(0,10)+
  ylab("Mean PACIER score")+
  geom_label(inherit.aes = FALSE, 
             data = . %>%
               group_by(FSM,Order, Group) %>%
               count(),
             aes(label = paste0(n, " Obs."), x = FSM),
             y = 0.5,
             # this is the line that fixes it
             position = position_dodge2(width = 0.8)
  )
2 Likes

Thanks for a great introduction to the Rstudio community! Your solution works perfectly and I appreciate the explanation.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.