Search code examples
rggplot2geom-text

position_dodge in geom_text()


Does anyone know, how I can position the geom_text() numbers in the example below so that one numer is above the point and one below the point? position_doge() seems not to work the way I would have expected.

Thanks!

library(tidyverse)
library(ggplot2)

# fake data
n <- 1000
df <- data.frame(value = runif(n, 1, 5),
                 grp = sample(c("A", "B", "C"), size = n, replace = T),
                 grp2 = sample(c("A", "B"), size = n, replace = T),
                 var = sample(c("var1", "var2", "var3"), size = n, replace = T))

# plot
df %>% group_by(var, grp, grp2) %>%
  summarise(mw = mean(value, na.rm=TRUE),
            sd = sd(value, na.rm = TRUE)/2,
            n = n(),
            uci = t.test(value, conf.level = .95)$conf.int[[2]],
            lci = t.test(value, conf.level = .95)$conf.int[[1]]) %>%
  
  ggplot(aes(x = grp, y = mw, color = grp2)) +
    geom_point(size=3, alpha=.5, pch = 15, position = position_dodge(width=0.7)) +
    geom_errorbar(aes(ymin=lci, ymax=uci), lwd=1, width=.5, alpha=.8, position = position_dodge(width=0.7), na.rm=T) +
    geom_text(aes(label = round(mw, 1)), color = "black", position = position_dodge(width=2), size = 3, show.legend = FALSE) +
    coord_flip() +
    facet_grid(var ~ .) +
    scale_y_continuous(limits = c(1, 5)) 

Solution

  • To make position_dodge work for your geom_text layer you have to map on the group aesthetic to dodge the labels by grp2. Additionally I added an ifelse to conditionally set the alignment of the labels.

    library(tidyverse)
    
    set.seed(123)
    
    # plot
    df %>%
      group_by(var, grp, grp2) %>%
      summarise(
        mw = mean(value, na.rm = TRUE),
        sd = sd(value, na.rm = TRUE) / 2,
        n = n(),
        uci = t.test(value, conf.level = .95)$conf.int[[2]],
        lci = t.test(value, conf.level = .95)$conf.int[[1]]
      ) %>%
      ggplot(aes(x = grp, y = mw, color = grp2)) +
      geom_point(size = 3, alpha = .5, pch = 15, position = position_dodge(width = 0.7)) +
      geom_errorbar(aes(ymin = lci, ymax = uci), lwd = 1, width = .5, alpha = .8, position = position_dodge(width = 0.7), na.rm = T) +
      geom_text(
        aes(
          label = round(mw, 1), group = grp2,
          vjust = if_else(grp2 == "A", 0, 1)
        ),
        color = "black", position = position_dodge(width = 2), size = 3, show.legend = FALSE
      ) +
      coord_flip() +
      facet_grid(var ~ .) +
      scale_y_continuous(limits = c(1, 5))
    

    enter image description here