Raincloud-Plot in R: Verteilung, Boxplot und Rohdaten in einem

R
ggplot2
Visualisierung
Wahlen
Autor:in

DI Dr. Johannes Hofrichter

Veröffentlichungsdatum

20. Juli 2026

Ein Raincloud-Plot zeigt drei Sichten auf dieselben Daten gleichzeitig: die Dichtekurve als „Wolke”, den Boxplot mit Median und Quartilen und die einzelnen Rohwerte als „Regen” darunter.

Der klassische Boxplot fasst eine Verteilung auf fünf Kennzahlen zusammen – praktisch, aber er verschweigt, wie die Werte tatsächlich liegen. Zwei völlig verschiedene Verteilungen können denselben Boxplot ergeben. Der Raincloud-Plot umgeht das, indem er Dichtekurve, Boxplot und Rohdaten übereinanderlegt: Form, Streuung und jeder einzelne Punkt auf einen Blick. Ich zeige das an der Wahlbeteiligung bei der Nationalratswahl 2024, heruntergebrochen auf jede einzelne Gemeinde und gruppiert nach Bundesland.

Die Daten

Die Rohdaten kommen vom Bundesministerium für Inneres (endgültiges Ergebnis der Nationalratswahl 2024). Das ist eine Excel-Datei mit einer Zeile je Gemeinde, die ich mit read_excel() einlese.

Code: Daten laden
library(readxl)
library(dplyr)
library(stringr)

xlsx <- "nrw2024-bundeswahlbehoerde.xlsx"
download.file(
  paste0(
    "https://www.bmi.gv.at/412/Nationalratswahlen/Nationalratswahl_2024/",
    "files/endgueltiges_ergebnis_beschluss_bundeswahlbehoerde_16102024.xlsx"
  ),
  xlsx, mode = "wb"
)
wahl_raw <- read_excel(xlsx, sheet = 1)

Aufbereiten

Aus der Gemeindekennziffer (GKZ) filtere ich die echten Gemeinden heraus – Bundesland-Summen und Wahlkarten-Zeilen fliegen raus. Aus dem zweiten Zeichen der GKZ leite ich das Bundesland ab und berechne die Wahlbeteiligung als Anteil der abgegebenen an den wahlberechtigten Stimmen. Zum Schluss sortiere ich die Bundesländer nach ihrer Median-Wahlbeteiligung, damit die y-Achse später eine sinnvolle Reihenfolge hat.

Code: Daten aufbereiten
bl_names <- c(
  "1" = "Burgenland", "2" = "Kärnten", "3" = "Niederösterreich",
  "4" = "Oberösterreich", "5" = "Salzburg", "6" = "Steiermark",
  "7" = "Tirol", "8" = "Vorarlberg", "9" = "Wien"
)

wahl <- wahl_raw |>
  filter(
    str_detect(GKZ, "^G[1-9][0-9]{4}$"),
    !str_detect(GKZ, "^G[0-9]{3}00$"),
    Wahlberechtigte > 0
  ) |>
  mutate(
    bl_code         = str_sub(GKZ, 2, 2),
    bundesland      = bl_names[bl_code],
    wahlbeteiligung = 100 * Abgegebene / Wahlberechtigte
  ) |>
  filter(!is.na(bundesland))

# Bundesländer nach Median-Wahlbeteiligung sortieren (für die y-Achse)
bl_order <- wahl |>
  group_by(bundesland) |>
  summarise(med = median(wahlbeteiligung), .groups = "drop") |>
  arrange(med) |>
  pull(bundesland)

wahl <- wahl |>
  mutate(bundesland = factor(bundesland, levels = bl_order)) |>
  select(bundesland, wahlbeteiligung)

Die Grafik

Die „Wolke” entsteht durch stat_halfeye() aus dem Paket ggdist – eine halbe Dichtekurve mit zwei Intervallbändern (50 % und 95 %). Über justification = -0.15 schiebe ich sie nach oben, darunter setze ich mit geom_boxplot() einen schmalen Boxplot und mit geom_point() den „Regen” der einzelnen Gemeinden, leicht nach unten versetzt und transparent. Die Spectral-Palette gibt jedem Bundesland eine eigene Farbe.

Code: Grafik
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 der Nationalratswahl 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.

Die Grafik liest sich so: Die obere Wolke zeigt die Form der Verteilung, der Boxplot in der Mitte Median und Quartile, jeder Punkt unten ist eine Gemeinde. Bundesländer mit breiter Wolke und weit gestreuten Punkten sind in sich uneinheitlicher als solche mit kompakter Verteilung. Als Variante können Sie statt des Boxplots nur das Intervallband zeigen oder die Punkte mit geom_jitter() stärker auffächern.


Eigene Daten so darstellen?

Aussagekräftige Grafiken sind für mich der sichtbare Teil einer sauberen Datenanalyse. Wenn Sie ggplot2 und ggdist selbst beherrschen möchten, ist der Visualisierungskurs der richtige Einstieg. Weitere moderne Diagrammtypen zeige ich im Ridgeline-Plot, im Dumbbell-Chart und im Bump-Chart.

Zurück nach oben