Moderne ggplot2-Grafiken: vier Beispiele mit echten Daten

R
ggplot2
Visualisierung
Wien
Autor:in

DI Dr. Johannes Hofrichter

Veröffentlichungsdatum

3. Juni 2026

Ein Balkendiagramm ist schnell gebaut, aber selten die beste Wahl. Sobald Daten eine Verteilung, eine Entwicklung über die Zeit oder einen Vergleich zwischen Gruppen erzählen, lohnt sich ein Blick über die Standardgrafik hinaus. In diesem Beitrag zeige ich vier Diagrammtypen, die ich im Visualisierungskurs ausführlicher behandle – jeweils mit echten, offen verfügbaren Daten und vollständigem ggplot2-Code zum Aufklappen.

Die Datenaufbereitung läuft in einem eigenen Skript (daten-aufbereiten.R), das die Rohdaten holt und vier schlanke Datensätze speichert. Die Code-Blöcke hier lesen nur diese vorbereiteten Daten und konzentrieren sich auf die Grafik selbst.

Ridgeline: wie sich Temperaturverteilungen verschieben

Ein Ridgeline-Plot stapelt mehrere Dichtekurven leicht versetzt übereinander. Das eignet sich, um zu zeigen, wie sich eine ganze Verteilung über Gruppen verändert – nicht nur ein Mittelwert. Hier sind es die Tagesmittel-Temperaturen der Station Wien Hohe Warte, gruppiert nach Jahrzehnt. Man sieht, wie sich die gesamte Verteilung über die Dekaden nach rechts, also zu wärmeren Werten, verschiebt.

Code
ggplot(temp, aes(x = t, y = decade, fill = after_stat(x))) +
  geom_density_ridges_gradient(
    scale = 2.2, rel_min_height = 0.01,
    quantile_lines = TRUE, quantiles = 2
  ) +
  scale_fill_gradientn(
    name = "°C",
    colours = rev(RColorBrewer::brewer.pal(11, "RdYlGn"))
  ) +
  scale_x_continuous(breaks = seq(-15, 35, 5)) +
  labs(
    title    = "Wien wird wärmer",
    subtitle = "Tagesmittel-Temperaturen Wien Hohe Warte je Dekade, 1960–2024",
    x        = "Tagesmittel-Temperatur (°C)",
    y        = NULL,
    caption  = "Daten: GeoSphere Austria (klima-v1-1d, Station 105). Linie = Median."
  ) +
  theme_minimal(base_size = 12) +
  theme(
    legend.position  = "none",
    plot.title       = element_text(face = "bold", size = 18),
    plot.subtitle    = element_text(colour = "grey40", margin = margin(b = 12)),
    panel.grid.minor = element_blank()
  )

Ridgeline-Plot der Tagesmittel-Temperaturen in Wien je Dekade von 1960 bis 2024. Die Verteilungen verschieben sich über die Jahrzehnte zu wärmeren Werten.

Raincloud: Rohdaten, Verteilung und Median in einem Bild

Der Raincloud-Plot kombiniert drei Sichten auf dieselben Daten: eine halbe Dichtekurve (die “Wolke”), einen kompakten Boxplot und die einzelnen Beobachtungen als Punkte (der “Regen”). So bleibt die Verteilung sichtbar, ohne die Rohdaten zu verstecken. Im Beispiel ist es die Wahlbeteiligung der Nationalratswahl 2024 – jeder Punkt eine Gemeinde, gruppiert nach Bundesland.

Code
ggplot(wahl, aes(x = wahlbeteiligung, y = bundesland, fill = bundesland)) +
  stat_halfeye(
    adjust = 0.6, width = 0.7, .width = c(0.5, 0.95),
    justification = -0.15, point_colour = NA, alpha = 0.85
  ) +
  geom_boxplot(
    width = 0.18, outlier.shape = NA, alpha = 0.6, colour = "grey20"
  ) +
  geom_point(
    position = position_nudge(y = -0.18),
    size = 0.6, alpha = 0.25, colour = "grey25"
  ) +
  scale_fill_brewer(palette = "Spectral", guide = "none") +
  scale_x_continuous(
    breaks = seq(40, 100, 10), labels = function(x) paste0(x, " %")
  ) +
  labs(
    title    = "Wo wurde 2024 stärker gewählt?",
    subtitle = "Wahlbeteiligung der Nationalratswahl 2024 je Gemeinde, nach Bundesland",
    x        = "Wahlbeteiligung (Abgegebene / Wahlberechtigte)",
    y        = NULL,
    caption  = "Daten: BMI – Endgültiges Ergebnis NRW 2024. Jeder Punkt = eine Gemeinde."
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.title         = element_text(face = "bold", size = 18),
    plot.subtitle      = element_text(colour = "grey40", margin = margin(b = 12)),
    plot.caption       = element_text(colour = "grey50", hjust = 0),
    panel.grid.minor   = element_blank(),
    panel.grid.major.y = element_blank()
  )

Raincloud-Plot der Wahlbeteiligung bei der Nationalratswahl 2024 je Gemeinde, gruppiert nach Bundesland.

Dumbbell: zwei Zeitpunkte direkt vergleichen

Ein Dumbbell-Chart verbindet zwei Werte pro Kategorie mit einer Linie – ideal für einen Vorher-Nachher-Vergleich. Hier ist es die Lebenserwartung bei Geburt in den EU-27-Ländern, 2010 gegenüber 2023. Die Länge der Linie zeigt den Zugewinn, die Sortierung stellt die größten Sprünge nach oben.

Code
col_2010 <- "#D4A843"  # Gold
col_2023 <- "#1B365D"  # Navy

ggplot() +
  geom_segment(
    data = le_wide,
    aes(x = y2010, xend = y2023, y = land, yend = land, colour = delta),
    linewidth = 1.8, lineend = "round"
  ) +
  geom_point(
    data = filter(le_long, year == 2010),
    aes(x = le, y = land), colour = col_2010, size = 3.4
  ) +
  geom_point(
    data = filter(le_long, year == 2023),
    aes(x = le, y = land), colour = col_2023, size = 3.4
  ) +
  scale_colour_gradient(
    low = "#E5E7EB", high = "#1B365D", name = "Δ (Jahre)",
    breaks = c(1, 2, 3, 4),
    guide = guide_colourbar(
      barwidth = unit(8, "lines"), barheight = unit(0.4, "lines"),
      title.position = "top", title.hjust = 0
    )
  ) +
  scale_x_continuous(
    breaks = seq(72, 84, 2), labels = function(x) paste0(x, " J.")
  ) +
  labs(
    title    = paste0(
      "<span style='color:", col_2010, "'>2010</span> &nbsp;→&nbsp; ",
      "<span style='color:", col_2023, "'>2023</span>: Lebenserwartung in der EU"
    ),
    subtitle = "Lebenserwartung bei Geburt, EU-27 – sortiert nach Zugewinn (größter Sprung oben)",
    x        = "Lebenserwartung bei Geburt (Jahre)",
    y        = NULL,
    caption  = "Daten: Eurostat (demo_mlexpec), beide Geschlechter."
  ) +
  theme_minimal(base_size = 11) +
  theme(
    plot.title           = element_markdown(face = "bold", size = 17),
    plot.subtitle        = element_text(colour = "grey40", margin = margin(b = 12)),
    plot.caption         = element_text(colour = "grey50", hjust = 0),
    legend.position      = "top",
    legend.justification = "left",
    panel.grid.minor     = element_blank(),
    panel.grid.major.y   = element_blank(),
    axis.text.y          = element_text(size = 10)
  )

Dumbbell-Chart der Lebenserwartung in den EU-27-Ländern, 2010 gegenüber 2023, sortiert nach Zugewinn.

Bump-Chart: Rangwechsel über die Zeit

Ein Bump-Chart verfolgt Ränge über die Zeit. Statt absoluter Werte zählt die Reihenfolge – wer steigt auf, wer fällt zurück. Hier sind es die beliebtesten Vornamen für Neugeborene in Wien zwischen 2014 und 2023, getrennt nach Buben und Mädchen. Die Farbflächen greifen die Markenfarben der Website auf: Navy als Hintergrund, helles Gold für die Beschriftung.

Code
endpoints <- vornamen |>
  group_by(geschlecht) |>
  filter(jahr == max(jahr)) |>
  ungroup()

navy      <- "#1B365D"
gold_hell <- "#E9C46A"

ggplot(vornamen, aes(x = jahr, y = rang, colour = name)) +
  geom_bump(linewidth = 2, smooth = 8, alpha = 0.9) +
  geom_point(size = 3.6) +
  geom_text(
    data = endpoints, aes(label = name),
    hjust = 0, nudge_x = 0.18, size = 4.4, fontface = "bold",
    colour = gold_hell
  ) +
  facet_wrap(~ geschlecht, ncol = 2, scales = "free_y") +
  scale_y_reverse(breaks = 1:8) +
  scale_x_continuous(
    breaks = seq(2014, 2022, 2),
    limits = c(2014, 2023 + 2.2), expand = c(0.02, 0)
  ) +
  scale_colour_manual(
    values = colorRampPalette(
      RColorBrewer::brewer.pal(8, "Set2")
    )(n_distinct(vornamen$name))
  ) +
  guides(colour = "none") +
  labs(
    title    = "Rangwechsel der Top-Vornamen in Wien",
    subtitle = "Top 8 der beliebtesten Vornamen, Buben und Mädchen, 2014–2023",
    x        = NULL,
    y        = "Rang (1 = häufigster Name)",
    caption  = "Daten: Stadt Wien, Vornamen Neugeborene (CC-BY 4.0)."
  ) +
  theme_minimal(base_size = 12) +
  theme(
    plot.background    = element_rect(fill = navy, colour = NA),
    panel.background   = element_rect(fill = navy, colour = NA),
    plot.title         = element_text(face = "bold", size = 20, colour = gold_hell),
    plot.subtitle      = element_text(colour = "grey80", margin = margin(b = 12)),
    plot.caption       = element_text(colour = "grey65", hjust = 0),
    strip.text         = element_text(face = "bold", size = 13, colour = gold_hell),
    axis.title         = element_text(colour = gold_hell),
    axis.text          = element_text(colour = "grey85"),
    axis.text.x        = element_text(size = 11, colour = "grey85"),
    panel.grid.minor   = element_blank(),
    panel.grid.major.x = element_blank(),
    panel.grid.major.y = element_line(colour = "grey30")
  )

Bump-Chart der Top-8-Vornamen für Neugeborene in Wien von 2014 bis 2023, getrennt nach Buben und Mädchen.

Weiterlernen

Diese vier Diagrammtypen sind Teil des Visualisierungskurses, in dem ich den Weg von den Rohdaten bis zur publikationsreifen Grafik Schritt für Schritt durchgehe – inklusive Theming, Farben und reproduzierbarem Workflow.

Zurück nach oben