rggplot2geom-text

In r: geom_text label shifts horizontal position between dodged bars


In the following ggplot in r, I would like my "n" labels to be aligned with the left side of each bar — as they are on the pink bars but not on the blue bars. Somehow, the dodging is not transferring to the n label for the right-hand blue bars.

I've looked at Position geom_text on dodged barplot which suggests using dodge(0.9). This has not helped in my case. This answer: Add text on top of a faceted dodged bar chart led me to add the "group = " in my ggplot code. This didn't help.

All help would be appreciated and please let me know if I can add any clarification here!

enter image description here

Here's a minimal reproducible example:

factor <- c("Included", "Included", "Excluded", "Excluded")
affected <- c("Affected", "Not Affected", "Affected", "Not Affected")
mean_rating <- c(76.00000, 39.55556, 49.00000, 41.62069)
n <- c(23, 2, 17, 19)

df1 <- data.frame(factor, affected, mean_rating, n)

ggplot(df1, aes(x = factor, y = mean_rating, fill = affected, group = affected)) + 
  geom_bar(stat = "identity", position = position_dodge(0.9)) +
  geom_text(aes(label = paste("n =", n), y = mean_rating), 
            hjust = 1, vjust=-0.35, position = position_dodge(0.9)) +
  guides(fill = FALSE, color = FALSE)


Solution

  • The issue is that the labels are placed at the center of the bars and using hjust the labels are aligned to the left or the right of this position. Instead, to align the labels with the left of the bars you have to place the labels at the left of the bars, which for your case could be achieved by shifting the x position by -.9 / 2 / 2 (.9 / 2 = half of the bar width, and another ... / 2 to account for the number of fill categories). To this end I use stage(), i.e. x = stage(factor, after_stat = x - .9 / 4)

    library(ggplot2)
    
    ggplot(df1, aes(x = factor, y = mean_rating, fill = affected)) +
      geom_bar(stat = "identity", position = position_dodge(0.9)) +
      geom_text(
        aes(
          x = stage(factor, after_stat = x - .9 / 2 / 2),
          label = paste("n =", n), y = mean_rating
        ),
        hjust = 0,
        vjust = -0.35,
        position = position_dodge(0.9)
      ) +
      guides(fill = "none", color = "none")