Kapitel 11 Bausteine
In den nächsten Abschnitten schauen wir uns die verschiedene Bausteine einer ggplot2
Grafik genauer an. Dabei sehen wir auch eine Reihe von Beispielen, die uns zeigen, wie man die verschiedenen Bausteine miteinander verknüpft.
11.1 Aesthetics
Mit der Funktion aes()
lässt sich das Aussehen der Grafik regeln (nicht der Inhalt). Wir können z.B.
- die Position:
x
undy
- die Farbe:
color
undfill
- die Form:
shape
- den Linientyp:
linetype
- die Größe der Symbol:
size
festlegen. Die jeweiligen Werte dieser aesthetics können entweder fix oder in Abhängigkeit von Variablen aus dem verwendeten Datensatz gewählt werden.
Werden die Werte in Abhängigkeit der Daten gewählt, so definiert die Funktion aes()
ein mapping zwischen den Daten und den aesthetics der Grafik.
Nicht jedes aesthetic kann allerdings mit allen verfügbaren geoms kombiniert werden. So macht z.B. der linetype
ja wenig Sinn in geom_point()
. Eine Übersicht der möglichen aesthetics findet man in der Hilfe jeder geom-Funktion. In der Hilfe von geom_point()
findet man z.B.
geom_point {ggplot2} R Documentation
Points
Description
The point geom is used to create scatterplots. The scatterplot is most useful for displaying the relationship between two continuous variables. It can be used to compare one continuous and one categorical variable, or two categorical variables, but a variation like geom_jitter(), geom_count(), or geom_bin2d() is usually more appropriate. A bubblechart is a scatterplot with a third variable mapped to the size of points.
Usage
geom_point(
mapping = NULL,
data = NULL,
stat = "identity",
position = "identity",
...,
na.rm = FALSE,
show.legend = NA,
inherit.aes = TRUE
)
...
Aesthetics
geom_point() understands the following aesthetics (required aesthetics
are in bold):
x
y
alpha
colour
fill
group
shape
size
stroke
Learn more about setting these aesthetics in vignette("ggplot2-specs").
Will man über die Daten Werte für die verschiedenen aesthetics definieren, so muss dies innerhalb der aes()
Funktion geschehen. Werden Argumente auf fixe Werte gesetzt, so sind sie außerhalb der aes()
Funktion zu setzen.
In einem Plot der gdpPercap
Daten für Deutschland und Frankreich wollen wir anhand von unterschiedlichen Farben die Daten der beiden Länder unterscheiden. Dazu müssen wir nur colour
innerhalb von aes()
den Wert country
zuweisen. Zusätzlich wollen wir die Größe der zu zeichnenden Punkte etwas erhöhen. Aber die Größe soll für beide Länder gleich sein. Daher definieren wir size
außerhalb der aes()
Funktion.
gapminder |>
filter(country %in% c("Germany","France")) |>
ggplot(mapping = aes(x = year, y = gdpPercap, colour = country)) +
geom_point(size = 3)

11.2 Geoms
Mithilfe der geom_xxx()
Funktionen können wir die Daten als geometrische Formen (Punkte, Linien, …) in einer Grafik darstellen. Jede ggplot2
Grafik benötigt daher mindestens ein geom
. Beispiele sind
Da wir nicht alle verfügbaren geoms
auflisten können/wollen, sei an dieser Stelle auf die ggplot2 Seite verwiesen.
Im nächsten Beispiel stellen wir die gleichen Daten/Variablen über zwei verschiedene geoms
dar.
gapminder |>
ggplot(mapping = aes(x = year, y = gdpPercap)) +
geom_point()
gapminder |>
ggplot(mapping = aes(x = year, y = gdpPercap)) +
geom_smooth()
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'
Obwohl die gleichen Daten visualisiert wurden, ist das Ergebnis doch recht unterschiedlich. Der Scatterplot zeigt alle (abgesehen von Overplotting) Daten, wohingegen mit geom_smooth()
eine geglätteter Zusammenhang dargestellt wird.
Interessant sind hier natürlich die wenigen großen gdpPercap
Werte in der linken Grafik
gapminder |>
filter(gdpPercap > 50000)
## # A tibble: 6 × 6
## country continent year lifeExp pop gdpPercap
## <fct> <fct> <int> <dbl> <int> <dbl>
## 1 Kuwait Asia 1952 55.6 160000 108382.
## 2 Kuwait Asia 1957 58.0 212846 113523.
## 3 Kuwait Asia 1962 60.5 358266 95458.
## 4 Kuwait Asia 1967 64.6 575003 80895.
## 5 Kuwait Asia 1972 67.7 841934 109348.
## 6 Kuwait Asia 1977 69.3 1140357 59265.
Kuwait hat über den gesamten Zeitraum sehr hohe GDP Werte. Aber zu Beginn der Aufzeichnungen waren die Werte in Bezug auf die damals noch recht kleine Populationsgröße sogar außergewöhnlich hoch.
Einem ggplot
Objekt können wir nicht nur ein geom
zuordnen. Prinzipiell können wir beliebig viele weitere geoms
hinzufügen. Wir können also die gerade durchgeführte Glättung der Daten auch direkt zum Scatterplot hinzufügen
gapminder |>
ggplot(mapping = aes(x = year, y = gdpPercap)) +
geom_point() +
geom_smooth()
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

Wählen wir die Farbe eines geometrischen Objekts (oder mehrerer) anhand einer Faktorvariable, so erhalten wir automatisch eine entsprechende Legende
gapminder |>
ggplot(mapping = aes(x = year, y = gdpPercap)) +
geom_point(mapping = aes(colour = continent)) +
geom_smooth()
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

Beachtet dabei, dass wir colour
nur für geom_point()
gewählt haben. Die Glättung erfolgt weiterhin über alle Daten und nicht separat für jeden Kontinent. In diesem Fall haben wir in geom_point()
ein lokales mapping
definiert.
Aber natürlich hätten wir die Glättung auch pro Kontinent durchführen können. Dazu schreiben wir einfach colour
in das globale mapping
und löschen das lokale mapping in geom_point()
wieder.
gapminder |>
ggplot(mapping = aes(x = year, y = gdpPercap, colour = continent)) +
geom_point() +
geom_smooth()
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'

Nehmen wir mal an, dass uns nun aber die Punkte etwas zu groß sind und die Linien sollten nicht durchgezogen sein. D.h. wir würden gerne andere (aber fixe, nicht von Variablen abhängende) aesthetic Werte setzen. Das lässt sich schnell ändern.
gapminder |>
ggplot(aes(x = year, y = gdpPercap, colour = continent)) +
geom_point(size = 0.9) +
geom_smooth(linetype = 2)
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'

11.3 Statistische Transformationen
Jede geom_xxx()
Funktion besitzt eine “Standard-Statistik”, die beim Aufruf der Funktion berechnet wird.
args(geom_point)
## function (mapping = NULL, data = NULL, stat = "identity", position = "identity",
## ..., na.rm = FALSE, show.legend = NA, inherit.aes = TRUE)
## NULL
Bei einem Scatterplot ist die Statistik einfach nur die Identität.
Ein Balkendiagramm verwendet aber z.B.
args(geom_bar)
## function (mapping = NULL, data = NULL, stat = "count", position = "stack",
## ..., just = 0.5, width = NULL, na.rm = FALSE, orientation = NA,
## show.legend = NA, inherit.aes = TRUE)
## NULL
die Transformation count
. Das macht durchaus Sinn, da ja gezählt werden muss/soll wie viele Beobachtungen in die jeweilige Kategorie fallen.
Die jeweiligen Statistiken könnten über die entsprechenden stat_xxx()
Funktionen geplottet werden. Da aber jede geom_xxx()
Funktion mit mindestens einer dieser stat_xxx()
Funktionen verbunden ist, ist es oftmals einfacher direkt die entsprechende geom_xxx()
Funktion zu verwenden. Aber generell könnte die jeweilige stat_xxx()
Funktion auch direkt aufgerufen werden.
Daher liefern die beiden nachfolgenden Befehle auch die exakt gleiche Grafik
ggplot(gapminder, aes(x = continent)) +
geom_bar()
ggplot(gapminder, aes(x = continent)) +
stat_count()
Jedes geom
hat zwar ein Standard-Transformation, aber natürlich können oftmals noch weitere Transformationen berechnet/genutzt werden. Im Abschnitt Computed variables der Hilfe zu einem geom
sieht man alle verfügbaren Transformationen.
Für geom_bar()
sind dies
Computed variables
count
number of points in bin
prop
groupwise proportion
Die relativen Häufigkeiten berechnet man also über prop
. Dazu muss die y-Variable auf prop
gesetzt werden. Da der Aufruf
aber nach einer Variable prop
suchen würde, muss eine alternative Notation in diesem Fall verwendet werden
ggplot(gapminder, aes(x = continent, y = after_stat(prop))) +
geom_bar()

Der Befehl hat jetzt zwar eine Grafik erzeugt, aber die sieht noch nicht so aus, wie wir das erwartet haben. Die
relativen Häufigkeiten wurden innerhalb der fünf Gruppen berechnet und nicht über alle Beobachtungen. D.h. wir müssen der Funktion noch sagen, dass die relativen Häufigkeiten der fünf verschiedenen Ausprägungen (Kontinente) in eine Gruppe berechnet werden sollen. Dies geschieht über das group
aesthetic.
ggplot(gapminder, aes(x = continent, y = after_stat(prop))) +
geom_bar(aes(group = 1))

11.4 Scales
Scales steuern die Zuordnung von Daten zu aesthetics. Sie nehmen die Daten und bestimmen damit Größe, Farbe, Position oder Form von Objekten. Sie erlauben euch auch die Achsen und die Legend nach euren Vorstellungen anzupassen.
Man kann sicherlich mit ggplot2
Grafiken erstellen, ohne zu wissen, wie scales
funktionieren. Aber wenn ihr versteht wie scales
funktionieren und lernt, wie ihr sie einstellen könnt, werdet ihr viel mehr Kontrolle über eure Grafiken bekommen.
Über scale
Funktionen der Form scale_"aesthetic"_"type"
können wir aesthetics wie
-
color
undfill
position
size
shape
line type
modifizieren. Argumente dieser Funktionen sind z.B. name
, limits
, breaks
oder labels
.
Zuerst spielen wir etwas mit Farben. Dazu plotten wir erneut year
gegen gdpPercap
und wählen für jeden Kontinent eine eigene Farbe. Da wir die Farben über colour
definieren, verwenden wir Funktionen aus der Klasse scale_colour_xxx()
. Hätten wir beispielsweise Flächen über das aesthetic fill
mit Farbe gefüllt, so würden wir Funktionen aus der Klasse scale_fill_xxx()
verwenden um die Farben anzupassen.
(p <- gapminder |>
ggplot(aes(x = year, y = gdpPercap, colour = continent)) +
geom_point(size = 0.9) +
geom_smooth(linetype = 2) )
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'
p + scale_colour_brewer(palette = "Set1")
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'
# Farbpaletten von http://colorbrewer2.org/
p + scale_colour_grey(start = 0.1, end = 0.9) # keine so gute Wahl
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'
p + scale_colour_manual(
values = c("palevioletred3", "seagreen", "sienna1", "sienna4", "yellow"),
name = "Kontinent")
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'
In diesem Beispiel haben wir also die Farbe nachträglich über eine vorgegebene Palette, in Grau-Stufen bzw. manuell gewählt. Im letzten Beispiel haben wir zusätzlich noch den Titel der Legende geändert über das name
Argument.
Die Achsenbeschriftung der y-Achse ist nicht wirklich schön, weil nicht unbedingt selbsterklärend. Daher ändern wir im nächsten Schritt die Achsenbeschriftung.
p <- p +
scale_colour_manual(
values = c("palevioletred3", "seagreen", "sienna1", "sienna4", "yellow"))
p + scale_y_continuous("GDP pro Kopf")
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'

Da es sich bei gdpPercap
um eine stetige Variable handelt, haben wir scale_y_continuous()
verwendet (im Gegensatz zu scale_y_discrete()
) um die Achsenbeschriftung zu ändern. Über die Hilfsfunktion labs()
können wir die Beschriftung der Grafik aber auch einfacher/intuitiver ändern.
(p <- p + labs(x = "Jahr", y = "GDP pro Kopf",
title = "Monoton steigendes GDP pro Kopf",
subtitle = "Gestrichelte Linie zeigt Durchschnittswerte über alle
Länder pro Kontinent"))
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'

Die frühen Kuwait-Beobachtungen ziehen die y-Achse stark auseinander. Daher könnte man vielleicht etwas in den Plot hinein zoomen wollen. Dazu kann man das Koordinatensystem anpassen über coord_cartasian()
. Alternativ könnte man auch mit der Funktion ylim()
arbeiten (analog existiert natürlich auch xlim()
).
Verwendet man aber xlim()
bzw. ylim()
, so werden alle Datenpunkte, die nicht im zu plottenden Bereich liegen, aber nicht nur nicht gezeichnet, sondern auch aus dem Datensatz (für diesen einen Plot) entfernt. Dies hat dann Auswirkungen auf Teile des Plots, die auf statistische Transformationen basieren, welche mithilfe der vorhanden Daten berechnet werden.
p + ylim(0,55000)
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'
## Warning: Removed 6 rows containing non-finite outside the
## scale range (`stat_smooth()`).
## Warning: Removed 6 rows containing missing values or
## values outside the scale range (`geom_point()`).
(p <- p + coord_cartesian(ylim = c(0, 55000)))
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'
In der rechten Grafik ist der Verlauf der Kurven unverändert. In der linken Grafik hingegen liegt die Kurve für Asien nun bis Mitte der 80er Jahre deutlich unter der Kurve für Amerika.
Weitere (mögliche) Positionsänderungen ergeben sich durch Skalierungen der Achsen wie scale_x_log10()
, scale_y_sqrt()
oder
p + scale_x_reverse()
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'

Am Ende von diesem Abschnitt wollen wir nochmal ein Blick auf die Häufigkeitsverteilung bzgl. der verschiedenen Kontinente werfen. Diesmal wollen wir aber zusätzlich noch die GDP pro Kopf Werte berücksichtigen. Dazu teilen wir die GDP Werte in niedrig (kleiner als das 0.25 Quantil aller Beobachtungen), mittel (zwischen dem 0.25 und 0.75 Quantil aller Beobachtungen) und hoch (über dem 0.75 Quantil aller Beobachtungen) ein. Diese Information nutzen wir dann zum Einfärben der Balken
ggplot(gapminder,
aes(x = continent,
fill = cut(gdpPercap,
breaks = c(0, quantile(gdpPercap,0.25),
quantile(gdpPercap, 0.75),
max(gdpPercap))
)
)) +
geom_bar()

Wir erkennen, dass die notwendige Klassifizierung der GDP Werte im Plot Befehl erfolgen kann. Das produzierte Ergebnis ist aber natürlich nicht so überzeugend. Die Überschrift, wie die Beschriftungen der Legende müssen angepasst werden. Dazu verwenden wir die Funktion scale_fill_discrete()
.
q <- ggplot(gapminder,
aes(x = continent,
fill = cut(gdpPercap,
breaks = c(0, quantile(gdpPercap,0.25),
quantile(gdpPercap, 0.75),
max(gdpPercap))
)
))
q +
geom_bar() +
scale_fill_discrete(name = "GDP\nKlassifizierung",
labels = c("niedrig", "mittel", "hoch"))

In dieser Darstellung bleibt es bei einem Balken pro Kontinent. Würden wir aber gerne (bis zu) drei Balken pro Kontinent sehen, müssen die Positionierung ändern.
q +
geom_bar(position = "dodge") +
scale_fill_discrete(name = "GDP\nKlassifizierung",
labels = c("niedrig", "mittel", "hoch"))

Gefällt einem das kartesische Koordinatensystem nicht, könnte man beispielsweise mit Polarkoordinaten arbeiten.
q +
geom_bar(position = "dodge") +
scale_fill_discrete(name = "GDP\nKlassifizierung",
labels = c("niedrig", "mittel", "hoch")) +
coord_polar()

Für weitere Optionen sei hier auf die online Version der neuesten Auflage von ggplot2 (Wickham 2009) verwiesen.
11.5 Facets
Datensätze lassen sich oftmals bzgl. vorhandener Variablen gruppieren. Die zu untersuchenden Zusammenhänge zwischen weiteren Variablen sollten dann innerhalb dieser Gruppen dargestellt werden. Entsteht die Gruppierung basierend auf den Ausprägungen einer Variable, so kann man z.B. mit facet_wrap()
arbeiten
gapminder |>
ggplot(aes(x = year, y = gdpPercap )) +
geom_point(size = 0.9) +
geom_smooth(linetype = 2) +
facet_wrap(~ continent, ncol = 5)
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'

In der letzten Grafik verwenden alle fünf Plots die gleiche Skala auf der y-Achse um die Vergleichbarkeit der Werte zu erhöhen. In manchen Fällen mag dies aber störend sein. Mit dem Argument scales
könnt ihr die Skala “befreien”.
gapminder |>
ggplot(aes(x = year, y = gdpPercap )) +
geom_point(size = 0.9) +
geom_smooth(linetype = 2) +
facet_wrap(~ continent, ncol = 2, scales = "free")
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'

Erfolgt die Gruppierung anhand von zwei Variablen, so bietet facet_grid()
eine passende Aufteilung des Grafikfensters in Zeilen und Spalten. Neben dem Kontinent berücksichtigen wir jetzt auch noch die Populationsgröße des Landes. Konkret fragen wir ob die Population im entsprechenden Jahr größer als 5000000 ist, oder eben nicht.
gapminder |>
group_by(continent) |>
ggplot(aes(x = year, y = gdpPercap )) +
geom_point(size = 0.9) +
geom_smooth(linetype = 2) +
facet_grid(continent ~ pop > 5000000, scales = "free")
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'

Für Ozeanien erhalten wir so z.B. eine Unterteilung in Australien (TRUE
) und Neuseeland (FALSE
).
Die Beschriftung der Spalten sieht so natürlich nicht besonders schön aus. Ohne den Code ist die Beschriftung auch nicht zu verstehen, “Was ist wahr??”.
Daher versuchen wir die Beschriftung über das Argument labeller
der facet_grid()
Funktion zu ändern. Zulässige Werte für das Argument labeller
können über die labeller()
Funktion definiert werden. Hier hat man neben weiteren Optionen die Möglichkeit für jede Ausprägung der Variable, die eine Spalten- (oder Zeilen-) Aufteilung definiert, ein Label zu setzen. Dazu muss
die Variable über ihren Namen aufgerufen werden. Nun scheint es so, dass ein Aufruf über “Sondernamen” wie pop > 5000000
nicht funktioniert. Um trotzdem die Verwendung von labeller
zu illustrieren, definieren wir zuerst mit mutate
eine neue Variable pop5
und setzen anschließend die Labels über das Argument labeller
.
gapminder |>
mutate(pop5 = pop > 5000000) |>
group_by(continent) |>
ggplot(aes(x = year, y = gdpPercap )) +
geom_point(size = 0.9) +
geom_smooth(linetype = 2) +
facet_grid(continent ~ pop5, scales = "free",
labeller = labeller(
pop5 = c(`TRUE` = "pop large than 5 MM",
`FALSE` = "pop at most 5 MM")))
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'

11.6 Themes
Abschließend wollen wir noch über verschiedene themes
sprechen. Über themes
kann man das Aussehen der nicht datenbezogenen Elemente einer Grafik, wie z.B.
- die Beschriftungen
- den Hintergrund
- die Legende
- ….
verändern. Eine Reihe von themes
sind bereits vorhanden, wobei theme_gray()
das Default theme
ist. Siehe auch ?theme_gray()
.
p
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'
p + theme_bw()
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'
p + theme_dark()
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'
p + theme_minimal()
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'
Wir möchten nun gerne folgende Änderungen an der Grafik vornehmen:
- die Größe der Achsenbeschriftung ändern
- die Gitterlinien ohne Beschriftung entfernen
- die Legende in die Grafik verschieben
- die Hintergrundfarbe der Grafik und der Legende ändern
Die meisten dieser Änderungen können wir mit theme()
durchführen.
p <- p + scale_colour_brewer(palette = "Set1")
## Scale for colour is already present.
## Adding another scale for colour, which will
## replace the existing scale.
p +
theme(
axis.text = element_text(size = 14),
legend.key = element_rect(fill = "gold"),
legend.background = element_rect(fill = "#0065BD"),
legend.position = "bottom",
legend.text = element_text(colour = "white"),
panel.grid.major = element_line(colour = "grey40"),
panel.grid.minor = element_blank(),
panel.background = element_rect(fill = "gold")
)
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'

Ob das nun alles schön aussieht, sei dahingestellt, aber es zeigt durchaus die vorhandenen Möglichkeiten.
Will man gewisse Einstellung öfter verwenden, so kann man diese auch in einem theme
Objekt speichern und wiederverwenden.
mein_theme <- theme(
axis.text = element_text(size = 14),
legend.key = element_rect(fill = "hotpink3"),
panel.grid.major = element_line(colour = "grey40"),
panel.grid.minor = element_blank(),
panel.background = element_rect(fill = "navy")
)
class(mein_theme)
## [1] "theme" "gg"
p + mein_theme
## `geom_smooth()` using method = 'loess' and
## formula = 'y ~ x'

11.7 Buch zum Paket
Dieser Abschnitt konnte nur einen kleinen Einblick in die Möglichkeiten des ggplot2
Pakets geben. Eine ausführliche Beschreibung findet man im Buch zum Paket.
Findet man dort noch nicht die Funktionalität, die man sucht, sollte man einen Blick auf die ggplot2 extensions werfen. Oder vielleicht direkt dort starten.