79829109

Date: 2025-11-24 21:20:48
Score: 1
Natty:
Report link

The main problem happens when you filter the second dataset right here:

       data = data_2_schule_schulform %>%
         filter (Anzahl >= 3),

This subsets the data_2_schule_schulform object inside the geom_text call making it "misalign" with the data_2_schule_schulform inside the geom_bar() call just above it. Removing that and using the same ifelse logic you used before is the first fix. Second, you're passing fill into geom_text which is being ignored since it doesn't support it. You should be using group instead. The quick fix is, thus:

geom_text(
  data = data = data_2_schule_schulform,
  aes(
    group = Schulform,
    y = Anzahl * -1,
    x = Schuljahr,
    label = ifelse(
      Anzahl >= 3,
      comma(Anzahl, accuracy = 1L, big.mark = ".", decimal.mark = ","),
      ""
    )
  )
)

Part of the confusion with your example is because you're using two different datasets in a same plot. If possible, consider stacking the datasets into a single one: this would simplify it immensely.

That said, your code has several other problems you might consider reviewing:

  1. guides(alpha = 'none') is doing nothing.
  2. Both theme(legend.position = 'none') and labs(fill = 'none') are doing the same thing.
  3. geom_bar() should be used when you want the height of the bar to represent the count of cases. If you want the heights of the bars to represent values in the data, use geom_col(). In other words, geom_bar(stat = 'identity') is the same as geom_col() which you should be using.
  4. The comma function isn't actually doing anything since your numbers don't have decimals and the same goes for scale_y_continuous(labels = function(x) format(x, big.mark = ".")) since the numbers are all below 1000.
  5. size inside geom_hline is deprecated. Also, this horizontal line is actually making it hard to see the plot, consider removing it or making it smaller (e.g. linewidth = 0.8.

I took the liberty to make some adjustments to create a general solution to your problem.

  library(ggplot2)
  library(scales)
  library(dplyr)

  data_schule_schulform <- structure(
    list(
      Schuljahr = c(
        "2017",
        "2018",
        "2018",
        "2019",
        "2019",
        "2020",
        "2021",
        "2021",
        "2022",
        "2023",
        "2023",
        "2024",
        "2024",
        "2024"
      ),
      Herkunftsschulform = c(
        "Gymnasium",
        "Förderschule",
        "Gymnasium",
        "Förderschule",
        "Gymnasium",
        "Gymnasium",
        "Gesamtschule",
        "Gymnasium",
        "Gymnasium",
        "Gymnasium",
        "Sonstiges",
        "Förderschule",
        "Gymnasium",
        "Sonstiges"
      ),
      Anzahl = c(7, 2, 2, 1, 6, 2, 1, 2, 4, 1, 57, 1, 8, 44)
    ),
    class = c("tbl_df", "tbl", "data.frame"),
    row.names = c(NA, -14L)
  )

  data_2_schule_schulform <- structure(
    list(
      Schuljahr = c(
        "2017",
        "2018",
        "2019",
        "2019",
        "2019",
        "2021",
        "2022",
        "2022",
        "2023",
        "2023",
        "2023",
        "2024",
        "2024",
        "2024",
        "2024"
      ),
      Schulform = c(
        "Hauptschule",
        "Hauptschule",
        "Förderschule",
        "Gymnasium",
        "Hauptschule",
        "Hauptschule",
        "Gymnasium",
        "Hauptschule",
        "Förderschule",
        "Gesamtschule",
        "Hauptschule",
        "Förderschule",
        "Gesamtschule",
        "Gymnasium",
        "Hauptschule"
      ),
      Anzahl = c(3, 1, 1, 1, 5, 3, 1, 4, 1, 1, 2, 1, 1, 1, 9)
    ),
    class = c("tbl_df", "tbl", "data.frame"),
    row.names = c(NA, -15L)
  )

  df_text_positive <- data_schule_schulform |>
    mutate(
      label = ifelse(
        Anzahl >= 3,
        comma(Anzahl, accuracy = 1L, big.mark = ".", decimal.mark = ","),
        ""
      )
    )

  df_text_negative <- data_2_schule_schulform |>
    mutate(
      label = ifelse(
        Anzahl >= 3,
        comma(Anzahl, accuracy = 1L, big.mark = ".", decimal.mark = ","),
        ""
      )
    )

  
ggplot() +
  geom_col(
    data = data_schule_schulform,
    aes(fill = Herkunftsschulform, y = Anzahl, x = Schuljahr)
  ) +
  geom_text(
    data = df_text_positive,
    aes(
      group = Herkunftsschulform,
      y = Anzahl,
      x = Schuljahr,
      label = label
    ),
    position = position_stack(vjust = 0.5),
    size = 3,
    color = "black",
    fontface = "bold"
  ) +
  geom_col(
    data = data_2_schule_schulform,
    aes(fill = Schulform, y = Anzahl * -1, x = Schuljahr)
  ) +
  geom_text(
    data = df_text_negative,
    aes(
      group = Schulform,
      y = Anzahl * -1,
      x = Schuljahr,
      label = label
    ),
    position = position_stack(vjust = 0.5),
    size = 3,
    color = "black",
    fontface = "bold"
  ) +
  theme_minimal() +
  theme(
    legend.position = "none",
    axis.text.y = element_text(size = 8)
  )

Unfortunately, I can't post the finished image due to my low reputation. But the code above should work for your case.

Reasons:
  • RegEx Blacklisted phrase (1.5): low reputation
  • Long answer (-1):
  • Has code block (-0.5):
  • Low reputation (1):
Posted by: Vinícius Oike