Ein Dumbbell-Chart verbindet zwei Werte je Kategorie mit einer Linie – und macht so die Veränderung zwischen zwei Zeitpunkten viel deutlicher sichtbar als zwei nebeneinandergestellte Balken.
Wenn Sie für viele Gruppen einen Wert „vorher” und „nachher” gegenüberstellen wollen, ist der Dumbbell-Chart (nach der Hantelform benannt) die ruhigere Lösung: zwei Punkte pro Zeile, verbunden durch eine Linie, deren Länge die Differenz zeigt. Bei gruppierten Balken muss das Auge die Differenz selbst ausrechnen – hier liegt sie als Strecke vor Ihnen. Und sortiert man die Zeilen nach dieser Differenz, springt sofort ins Auge, wo sich am meisten getan hat. Ich zeige das an der Lebenserwartung bei Geburt in den EU-27-Ländern, 2010 gegenüber 2023.
Die Daten
Die Daten stammen von Eurostat (Datensatz demo_mlexpec, Lebenserwartung bei Geburt, beide Geschlechter). Die SDMX-API liefert die Zeitreihe direkt als TSV. Fehlende Werte sind dort mit : markiert, was ich beim Einlesen gleich als NA deklariere.
Die erste Spalte des Eurostat-TSV bündelt mehrere Dimensionen, die ich mit separate() zerlege, um den Ländercode zu bekommen. Ich behalte nur die 27 EU-Länder, übersetze die Codes ins Deutsche und bringe die Daten in zwei Formen: le_long (eine Zeile je Land und Jahr, für die Punkte) und le_wide (eine Zeile je Land mit beiden Jahren und der Differenz delta, für die Verbindungslinien). Beide werden nach delta sortiert, damit das Land mit dem größten Zugewinn oben steht.
Code: Daten aufbereiten
eu27 <-c(AT ="Österreich", BE ="Belgien", BG ="Bulgarien", CY ="Zypern",CZ ="Tschechien", DE ="Deutschland", DK ="Dänemark", EE ="Estland",EL ="Griechenland", ES ="Spanien", FI ="Finnland", FR ="Frankreich",HR ="Kroatien", HU ="Ungarn", IE ="Irland", IT ="Italien",LT ="Litauen", LU ="Luxemburg", LV ="Lettland", MT ="Malta",NL ="Niederlande", PL ="Polen", PT ="Portugal", RO ="Rumänien",SE ="Schweden", SI ="Slowenien", SK ="Slowakei")le_long <- le_raw |>rename(meta =1) |>separate(meta, into =c("freq", "unit", "sex", "age", "geo"), sep =",") |>mutate(geo =trimws(geo)) |>filter(geo %in%names(eu27)) |>select(geo, `2010`, `2023`) |>pivot_longer(c(`2010`, `2023`), names_to ="year", values_to ="le") |>mutate(le =as.numeric(trimws(gsub("[^0-9.]", "", le))),year =as.integer(year),land = eu27[geo] ) |>filter(!is.na(le))le_wide <- le_long |>pivot_wider(names_from = year, values_from = le, names_prefix ="y") |>filter(!is.na(y2010), !is.na(y2023)) |>mutate(delta = y2023 - y2010) |>arrange(delta)# Länder ohne vollständiges Paar raus, gemeinsame Faktor-Ordnung (Δ aufsteigend)le_long <- le_long |>filter(land %in% le_wide$land) |>mutate(land =factor(land, levels = le_wide$land))le_wide <- le_wide |>mutate(land =factor(land, levels = le_wide$land))
Die Grafik
Ich baue die Grafik aus drei Schichten: geom_segment() zieht die Hantel-Linie von 2010 nach 2023 (eingefärbt nach delta, also je größer der Zugewinn, desto dunkler), und zwei geom_point()-Aufrufe setzen die beiden Endpunkte in Gold (2010) und Navy (2023). Der Titel nutzt HTML-Farbauszeichnung, die über element_markdown() aus dem Paket ggtext gerendert wird – so erscheinen „2010” und „2023” im Titel direkt in ihren Punktfarben.
Code: Grafik
col_2010 <-"#D4A843"# Goldcol_2023 <-"#1B365D"# Navyggplot() +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> → ","<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) )
Zu lesen ist die Grafik so: Jede Zeile ist ein Land, der goldene Punkt steht für 2010, der dunkle für 2023, die Linie dazwischen für den Zugewinn. Weil oben die größten Sprünge stehen, sieht man sofort, welche Länder am stärksten aufgeholt haben – und am unteren Rand jene, die kaum zulegten oder sogar stagnierten. Als Variante könnten Sie die Linien zusätzlich mit Pfeilspitzen versehen oder die Differenz als Zahl ans Linienende schreiben.
Eigene Daten so darstellen?
Vergleiche zwischen zwei Zeitpunkten sind oft das Ergebnis einer gründlichen Datenanalyse – ich übernehme den Weg von der Quelle bis zur fertigen Grafik. Wenn Sie ggplot2 und ggtext selbst einsetzen möchten, ist der Visualisierungskurs der passende Rahmen. Weitere moderne Diagrammtypen finden Sie im Ridgeline-Plot, im Raincloud-Plot und im Bump-Chart.