Grundlagen von ggplot2

Übungsdaten

In diesem Kapitel verwenden wir Daten aus gapminder. Gapminder wurde 2005 in Stockholm gegründet und sammelt globale Statistiken unter anderem zu Gesundheit, wirtschaftlicher Entwicklung und Bevölkerungsentwicklung. Mit den folgenden Befehlen erhalten Sie Zugriff auf die Daten von Gapminder:

install.packages("gapminder")
library(gapminder)
gapminder

Gapminder enthält die Variablen country, continent, year, lifeExp (Lebenserwartung), pop (Bevölkerungszahl) und gdpPercap (BIP pro Kopf). Diese Daten sind unsere Übungsdaten.

country continent year lifeExp pop gdpPercap
Afghanistan Asia 1952 28.80100 8425333 779.4453
Afghanistan Asia 1957 30.33200 9240934 820.8530
Afghanistan Asia 1962 31.99700 10267083 853.1007
Afghanistan Asia 1967 34.02000 11537966 836.1971
Afghanistan Asia 1972 36.08800 13079460 739.9811
Afghanistan Asia 1977 38.43800 14880372 786.1134
Afghanistan Asia 1982 39.85400 12881816 978.0114
Afghanistan Asia 1987 40.82200 13867957 852.3959
Afghanistan Asia 1992 41.67400 16317921 649.3414
Afghanistan Asia 1997 41.76300 22227415 635.3414
Afghanistan Asia 2002 42.12900 25268405 726.7341
Afghanistan Asia 2007 43.82800 31889923 974.5803
Albania Europe 1952 55.23000 1282697 1601.0561
Albania Europe 1957 59.28000 1476505 1942.2842
Albania Europe 1962 64.82000 1728137 2312.8890
Albania Europe 1967 66.22000 1984060 2760.1969
Albania Europe 1972 67.69000 2263554 3313.4222
Albania Europe 1977 68.93000 2509048 3533.0039
Albania Europe 1982 70.42000 2780097 3630.8807
Albania Europe 1987 72.00000 3075321 3738.9327
Albania Europe 1992 71.58100 3326498 2497.4379
Albania Europe 1997 72.95000 3428038 3193.0546
Albania Europe 2002 75.65100 3508512 4604.2117
Albania Europe 2007 76.42300 3600523 5937.0295

Das Package ggplot2 hat eine übergeordnete Funktion: ggplot(). Wir beginnen damit, ggplot() zu schreiben und das Argument data anzugeben. Wenn dieser Code ausgeführt wird, erhalten wir die folgende Abbildung.

ggplot(data=gapminder)
Leeres graues Rechteck ohne Achsen, das Ergebnis von ggplot, wenn nur die Daten angegeben sind

Oben sehen wir nur ein leeres graues Rechteck. Das liegt daran, dass der Grafik zwei Komponenten fehlen:

  1. Ästhetisches Mapping: aes()
  2. Geometrische Komponenten: geom()

Wir fahren fort, indem wir aes() hinzufügen und dort angeben, dass x gleich year und y gleich pop ist. Das Ergebnis ist weiterhin eine leere Grafik, nun aber mit festgelegter x-Achse und y-Achse:

ggplot(data=gapminder,
       aes(x=year,
           y=pop))
Leere Grafik mit der x-Achse year und der y-Achse pop, aber ohne Datenpunkte

Die Grafik ist leer, weil ihr geom() fehlt, das die geometrischen Komponenten definiert. Wir fügen geom_points() hinzu, womit wir festlegen, dass wir Punkte in der Grafik sehen möchten:

ggplot(data=gapminder,
       aes(x=year,
           y=pop)) +
  geom_point()
Streudiagramm mit schwarzen Punkten für die Bevölkerung je Land gegen die Jahre 1952 bis 2007

Das bedeutet: In ggplot() legt man eine Datenquelle und ein ästhetisches Mapping (aes()) mit unter anderem x-Achse und y-Achse fest und fügt anschließend Ebenen mit geometrischen Komponenten hinzu (zum Beispiel geom_point()). geom_point() hat das ästhetische Mapping also von ggplot() geerbt!

Labels (Beschriftungen)

Beschriftungen verdeutlichen den Inhalt einer Grafik. Der englische Begriff lautet labels und wird im Folgenden auch hier verwendet. Labels werden mit der Funktion labs() angegeben. Sie können Labels für x-Achse, y-Achse, Titel, Untertitel, Bildunterschrift usw. festlegen. Ein Beispiel:

ggplot(data=gapminder,
       aes(x=year,
           y=pop)) +
  geom_point() +
  labs(x="Year",
       y="Population",
       tag="A",
       title="Titeln på grafen",
       subtitle="Undertiteln på grafen",
       caption="Figurförklaring hamnar här.")
Streudiagramm der Bevölkerung gegen das Jahr mit Tag A, Titel, Untertitel, Achsenbeschriftungen und Bildunterschrift

Allmählich werden es einige Zeilen Code. Damit klar ist, was in jedem Codeblock neu ist, wird dies im Folgenden mit dem Kommentar #NEU markiert.

Symbol eines Codefensters mit farbigen Codezeilen

Scientific notation deaktivieren

Beachten Sie die y-Achse der vorherigen Grafik. Die Werte werden in scientific notation (wissenschaftlicher Notation) dargestellt, die bei sehr großen oder sehr kleinen Zahlen aktiviert wird. Sie können dies mit folgendem Befehl deaktivieren:

options(scipen=999)

Wie oben erwähnt, erbt geom_point() das ästhetische Mapping (aes()) von ggplot(). Wir können dieses Mapping jedoch überschreiben, indem wir aes() in geom_point() angeben. Dann erbt geom_point() das Mapping nicht. Die folgende Grafik ist also identisch mit der vorherigen:

ggplot(data=gapminder) +
  # NEU
  geom_point(aes(x=year,
                 y=pop)) +
  labs(x="Year",
       y="Population",
       tag="A",
       title="Titeln på grafen",
       subtitle="Undertiteln på grafen",
       caption="Figurförklaring hamnar här.")
Streudiagramm der Bevölkerung gegen das Jahr mit Tag A, Titel, Untertitel, Achsenbeschriftungen und Bildunterschrift

Das ästhetische Mapping ganz oben zu definieren ist vorteilhaft, weil man es dann nicht in jedem geom() wiederholen muss.

Färben wir nun die Punkte nach dem Kontinent ein, zu dem sie gehören. Dies geschieht in aes(), indem wir color=continent angeben:

ggplot(data=gapminder, aes(x=year,
                           y=pop,
                           # NEU
                           color=continent)) +
  geom_point() +
  labs(x="Year",
       y="Population",
       tag="A",
       title="Titeln på grafen",
       subtitle="Undertiteln på grafen",
       caption="Figurförklaring hamnar här.")
Streudiagramm der Bevölkerung gegen das Jahr mit nach Kontinent eingefärbten Punkten und der Legende continent

Rechts neben der Grafik befindet sich die Farbkodierung, deren Label "continent" angepasst werden muss. Ein Label lässt sich in labs() mit dem Argument color angeben.

ggplot(data=gapminder, aes(x=year,
                           y=pop,
                           color=continent)) +
  geom_point() +
  labs(x="Year",
       y="Population",
       tag="A",
       title="Titeln på grafen",
       subtitle="Undertiteln på grafen",
       caption="Figurförklaring hamnar här.",
       # NEU
       color="Kontinent")
Dasselbe nach Kontinent eingefärbte Streudiagramm, nun mit dem Legendentitel Kontinent

In gapminder gibt es für jedes Land mehrere Zeilen. Im nächsten Schritt summieren wir die Bevölkerungszahl je Kontinent und Kalenderjahr. Dazu verwenden wir dplyr wie folgt:

gapminder_summary <- gapminder |>
  # Nach continent und year gruppieren
  group_by(continent, year) |>
  # Summe von pop berechnen (für jeden Kontinent und jedes Jahr)
  summarise(population = sum(pop)) |>
  # Gruppierung im Data Frame aufheben
  ungroup()

## Daten ansehen
gapminder_summary
continent year population
Africa 1952 237640501
Africa 1957 264837738
Africa 1962 296516865
Africa 1967 335289489
Africa 1972 379879541
Africa 1977 433061021
Africa 1982 499348587
Africa 1987 574834110
Africa 1992 659081517
Africa 1997 743832984
Africa 2002 833723916
Africa 2007 929539692
Americas 1952 345152446
Americas 1957 386953916
Americas 1962 433270254
Americas 1967 480746623
Americas 1972 529384210

Berechnen wir die Gesamtbevölkerung je Kontinent und Kalenderjahr:

ggplot(gapminder_summary,
       aes(x=year,
       y=population,
       color=continent)) +
  geom_point()
Punktdiagramm der Gesamtbevölkerung je Kontinent und Jahr, wobei Asien am höchsten liegt

Wir fügen eine Linie zwischen den Punkten hinzu, um den Trend deutlicher zu sehen:

ggplot(gapminder_summary,
       aes(x=year, y=population, color=continent)) +
  geom_point() +
  # NEU
  geom_line()
Liniendiagramm mit Punkten zur Gesamtbevölkerung je Kontinent von 1952 bis 2007

Mit geom_text() können Sie Text hinzufügen. Wir fügen nun geom_text() hinzu, um die Bevölkerungszahl an jedem Datenpunkt anzuzeigen. Auch geom_text() hat ein ästhetisches Mapping. Hier geben wir nur das Argument label an, das wir als die Variable population definieren. Der x-Wert und der y-Wert für geom_text() werden von ggplot() geerbt.

ggplot(gapminder_summary,
       aes(x=year, y=population, color=continent)) +
  geom_point() +
  geom_line() +
  # NEU
  geom_text(aes(label=population))
Liniendiagramm je Kontinent mit den Bevölkerungszahlen als Text an jedem Punkt, stark überlappend

Wir wiederholen genau dasselbe Vorgehen, jedoch mit geom_label() statt geom_text(). Mit geom_label() erhält der Text einen Hintergrund, der ihn besser sichtbar macht:

Liniendiagramm je Kontinent mit Bevölkerungszahlen in umrahmten Labels, die einander überlappen

Beide obigen Grafiken sind suboptimal, weil die Labels zu dicht beieinander stehen. Wir brauchen eine Funktion, die Labels automatisch voneinander trennen kann. Diese bietet das Package ggrepel, dessen Funktion geom_text_repel() Text automatisch auseinanderrückt. Das Package entfernt Datenpunkte, die sich nicht sinnvoll darstellen lassen. Das Ergebnis ist in der Regel zufriedenstellend:

install.packages("ggrepel")
library(ggrepel)
ggplot(gapminder_summary,
       aes(x=year, y=population, color=continent)) +
  geom_point() +
  geom_line() +
  # NEU
  geom_text_repel(aes(label=population))
Liniendiagramm je Kontinent, in dem die Bevölkerungszahlen mit ggrepel auseinandergerückt und mit Hilfslinien versehen sind

Das ist immer noch unübersichtlich. Möglicherweise ist es informativ genug, nur die Zahlen des ersten und des letzten Jahres anzugeben. Dazu berechnet man die maximale bzw. minimale Zahl der Menschen auf jedem Kontinent. Diese Berechnungen werden durchgeführt und in den Objekten max_population und min_population gespeichert, die anschließend ebenfalls in ggplot() verwendet werden:

## Berechnet die größte Bevölkerung jedes Kontinents
max_population <- gapminder_summary %>%
  group_by(continent) %>%
  arrange(continent, desc(population)) %>%
  distinct(continent, .keep_all = T)

## Berechnet die kleinste Bevölkerung jedes Kontinents
min_population <- gapminder_summary %>%
  group_by(continent) %>%
  arrange(continent, population) %>%
  distinct(continent, .keep_all = T)

## Visualisiert
ggplot(gapminder_summary,
       aes(x=year, y=population, color=continent)) +
  geom_point() +
  # NEU
  # Text für Maximalwerte
  geom_label_repel(data=max_population,
                  aes(x=year, y=population, color=continent, label=population)) +
  # NEU
  # Text für Minimalwerte
  geom_label_repel(data=min_population,
                  aes(x=year, y=population, color=continent, label=population))
Punktdiagramm je Kontinent mit Labels für die niedrigste und höchste Bevölkerung, platziert mit geom_label_repel

Nun verwenden wir geom_hline() und geom_vline(), um horizontale und vertikale Referenzlinien hinzuzufügen. Diese werden üblicherweise hinter den Datenpunkten platziert, weshalb sie im Code vor den Datenpunkten (geom_point()) deklariert werden müssen. Wir setzen Linien auf zwei Niveaus der y-Achse (festgelegt mit dem Argument yintercept), wie unten gezeigt:

ggplot(data=gapminder, aes(x=year,
                           y=pop,
                           color=continent)) +
  geom_point() +

  # NEU
  geom_hline(aes(yintercept=1000000000)) +
  geom_hline(aes(yintercept=500000000)) +

  labs(x="Year",
       y="Population",
       tag="A",
       title="Titeln på grafen",
       subtitle="Undertiteln på grafen",
       caption="Figurförklaring hamnar här.")
Streudiagramm der Bevölkerung je Kontinent mit horizontalen Referenzlinien bei 500 Millionen und 1 Milliarde

Mit geom_rect() lässt sich ein Bereich definieren, und zwar wie folgt:

ggplot(data=gapminder, aes(x=year,
                           y=pop,
                           color=continent)) +
  # NEU
  geom_rect(aes(xmin=1960, xmax=1990, ymin=500000000, ymax=100000000)) +

  geom_point() +

  labs(x="Year",
       y="Population",
       tag="A",
       title="Titeln på grafen",
       subtitle="Undertiteln på grafen",
       caption="Figurförklaring hamnar här.")
Streudiagramm der Bevölkerung je Kontinent mit einem dunklen Rechteck über die Jahre 1960 bis 1990

Mit geom_segment() können Sie besonders interessante Punkte markieren. Die Funktion hat das Argument arrow, um Pfeile zu zeichnen.

Beachten Sie, dass die y-Achse einen sehr großen Wertebereich mit großen Unterschieden zwischen den Datenpunkten aufweist. In solchen Fällen ist es vorteilhaft, die Variable zu logarithmieren. Wir logarithmieren die y-Achse, indem wir die Funktion scale_y_log10() hinzufügen, die alle y-Werte logarithmiert. Das bedeutet, dass Sie mathematische Berechnungen im Rahmen der Visualisierung durchführen können (die Datenquelle wird nicht verändert).

ggplot(data=gapminder, aes(x=year,
                           y=pop,
                           color=continent)) +
  geom_point() +
  # NEU
  scale_y_log10()
Streudiagramm der Bevölkerung je Kontinent gegen das Jahr mit logarithmischer y-Achse