Search code examples
rggplot2facet-wrapgeom-text

Position of geom_text in stacked geom bar with facet_wrap


in some of my plots I have trouble to position the geom_text the way I want to. Especially in stacked geom bars with facets (and if i would like to add the geom_text only for one of the expressions) it seems very tricky sometimes. Here I would like to position the geom_text in each facet in the center only of the green expression for the year "22". With my current code it is obviously not working. Does anybody know how to fix this?

Would be much appreciated!

This is my Code:

p2 <- ggplot() +
  geom_bar(
    data = data, 
    aes(fill = Empfehlung, y = Anteil, x = year), 
    position = 'stack', stat = 'identity') +
  facet_wrap(Name~ ., ncol = 3) +
  labs(
    title = "Einzelbetrachtung",
    x = "",
    y = "",
    fill = ""  
  ) +
  scale_y_continuous(labels = function(x) format(x, big.mark = ".")) + 
  scale_fill_manual(values = farben) +
  theme_minimal() +
  theme(
    legend.position='none',
    axis.text.x = element_text(size = 9, face = "bold"),
    axis.text.y = element_blank(),
    strip.text = element_text(face = "bold", size = 9.0)
  ) +
  geom_text(
    data = data %>%
      filter(
        year == "22",
        Empfehlung == "Realschule"
      ),
    aes(fill = Empfehlung, y = Anteil, x = year, label = paste0(format(Anteil, nsmall = 1), "")),
    position = position_stack(vjust = 0.5), size = 2.5, color= "black")

enter image description here


Solution

  • The issue is that you filtered the data for the category you want to label. This way position="stack" will not work as there are no values to stack. Instead, keep all observations and use an ifelse to label only the desired category.

    Using some fake random example data:

    library(dplyr, warn = FALSE)
    library(ggplot2)
    
    set.seed(123)
    
    # Create fake data
    data <-
      expand.grid(
        Empfehlung = c("Hauptschule", "Realschule", "Gymnasium"),
        year = 13:22,
        Name = paste0("facet", 1:4)
      ) |>
      mutate(Anteil = runif(n())) |>
      group_by(year, Name) |>
      mutate(Anteil = 100 * Anteil / sum(Anteil))
    
    ggplot(data, aes(y = Anteil, x = year, fill = Empfehlung)) +
      geom_col(
        position = "stack"
      ) +
      facet_wrap(Name ~ ., ncol = 2) +
      labs(
        title = "Einzelbetrachtung",
        x = "",
        y = "",
        fill = ""
      ) +
      # scale_fill_manual(values = farben) +
      theme_minimal() +
      theme(
        # legend.position = "none",
        axis.text.x = element_text(size = 9, face = "bold"),
        axis.text.y = element_blank(),
        strip.text = element_text(face = "bold", size = 9.0)
      ) +
      geom_text(
        data = data %>%
          filter(
            year == "22"
          ),
        aes(
          label = ifelse(
            Empfehlung == "Realschule",
            scales::number(Anteil, accuracy = .1),
            ""
          )
        ),
        position = position_stack(vjust = 0.5), size = 2.5, color = "black"
      )