library(tidyverse)
library(haven)
<- read_sav("data/beispieldaten.sav") |>
beispieldaten # Faktoren konvertieren und SPSS-Labels zuweisen
mutate(across(where(is.labelled), haven::as_factor)) |>
# Labels der Bildungsfaktoren vereinfachen
mutate(across(c(bildung_vater, bildung_mutter),
fct_recode(x,
\(x) Hauptschule = "Hauptschulabschluss oder niedriger",
Realschule = "Realschulabschluss (mittlere Reife)",
Abitur = "Fachabitur, Abitur",
Hochschule = "Fachhochschulabschluss, Universitätsabschluss")))
5 Grafiken mit ggplot2
Grafiken sind für die Datenanalyse sehr wichtig. Einerseits können wir sie für explorative Datenanalyse einsetzen, um eventuell verborgene Zusammenhänge zu entdecken oder uns einfach einen Überblick zu verschaffen. Andererseits brauchen wir Grafiken, um Resultate darzustellen und anderen zu kommunizieren.
Wir haben schon mehrmals in diesem Skript Grafiken mit dem Package ggplot2
erstellt, ohne uns den Code genauer anzuschauen. In diesem Kapitel werden wir nun die Syntax von ggplot2
kennenlernen.
Im Gegensatz dazu basiert ggplot2
auf einer intuitiven Syntax, der sogenannten Grammar of graphics. Sobald man sich daran gewöhnt hat, kann man mit einer eleganten und konsistenten “Grammatik” sehr komplexe Grafiken erstellen. ggplot2
ist darauf ausgelegt, mit tidy
Data zu arbeiten, d.h. wir brauchen Datensätze im long Format. Grafiken werden nun immer nach demselben Prinzip erstellt:
Schritt 1: Wir beginnen mit einem Datensatz und erstellen ein Plot-Objekt mit der Funktion ggplot()
.
Schritt 2: Wir definieren sogenannte “aesthetic mappings”, d.h. wir bestimmen welche Variablen auf den X-, bzw. Y-Achsen dargestellt werden sollen, und welche Variablen benutzt werden, um die Daten zu gruppieren. Die Funktion, welche wir dafür benutzen heisst aes()
.
Schritt 3: Wir fügen dem Plot eine oder mehrere “Layers” oder “Schichten” hinzu. Diese Layers definieren, wie etwas dargestellt werden soll, z.B. als Linie oder als Histogramm. Die Funktionen beginnen mit dem Präfix geom_
, z.B. geom_line()
.
Um ggplot2
zu benutzen brauchen wir nun noch einen zusätzlichen Operator: +
. Diesen kennen Sie bereits als mathematischen Operator, aber in diesem Zusammenhang bedeutet die Verwendung von +
, dass wir einzelne Elemente eines Plot-Objektes zusammenfügen.
Nach dieser etwas abstrakten Einführung illustrieren wir diese Schritte an einem praktischen Beispiel.
Am Ende des letzten Kapitels haben wir den Zusammenhang zwischen psychischem Stress und Geschlecht untersucht. Wir laden nun nochmals den Datensatz:
und erstellen einen Datensatz, der nur die Variablen ID
, geschlecht
und stress_psychisch
enthält.
<- beispieldaten |>
stress select(ID, geschlecht, stress_psychisch) |>
drop_na()
stress
# A tibble: 284 × 3
ID geschlecht stress_psychisch
<dbl> <fct> <dbl>
1 1 weiblich 1.67
2 2 männlich 3.5
3 10 weiblich 3.67
4 11 weiblich 1.5
5 12 weiblich 2.5
6 14 männlich 1
7 15 männlich 2.5
8 16 weiblich 3.5
9 17 männlich 1.67
10 18 männlich 2.5
# ℹ 274 more rows
In diesem Datensatz haben wir eine numerische Variable, stress_psychisch
und eine Gruppierungsvariable, geschlecht
. Wir wollen die Verteilung von stress_psychisch
zwischen männlichen und weiblichen Jugendlichen vergleichen. Die Verteilung können wir auf verschiedene Arten grafisch darstellen: mit Punkten, einem Boxplot oder einem Violin-Plot. Diese drei Methoden sind in der Sprache von ggplot2
verschiedene geoms
und können so benutzt werden: geom_point()
, geom_boxplot()
oder geom_violin()
. Zusätzlich gibt es noch eine Funktion geom_jitter()
, welche die Punkte in einem Punktdiagramm nicht aufeinander zeichnet, sondern mit einem räumlichen “jittering” (Flackern) versieht.
Das ggplot2
Package können wir entweder individuell oder als Teil des tidyverse
laden:
library(ggplot2)
# oder
library(tidyverse)
5.1 Schritt 1: Plot-Objekt erstellen
Wir beginnen mit einem Datensatz und erstellen ein Plot-Objekt mit der Funktion ggplot()
. Diese Funktion hat als erstes Argument einen Dataframe. Dies bedeutet, dass wir den pipe
Operator verwenden können:
Wir haben also zwei Möglichkeiten. Wir bevorzugen hier die pipe
Notation, aber es ist selbstverständlich auch möglich, den Dataframe innerhalb der Funktion als Argument anzugeben. Gleichzeitig weisen wir das Objekt einer Variablen zu, und nennen diese p
.
# 1. Variante
<- ggplot(data = stress)
p
# 2. Variante
<- stress |>
p ggplot()
5.2 Schritt 2: Aesthetic mappings
Nun definieren wir mit dem zweiten Argument mapping
die “aesthetic mappings”. Diese bestimmen, wie die Variablen benutzt werden, um die Daten darzustellen, und werden mit der Funktion aes()
definiert. Wir wollen die Gruppierungsvariable geschlecht
auf der X-Achse darstellen und stress_psychisch
soll auf der Y-Achse angezeigt werden. Zusätzlich kann aes()
weitere Argumente haben: fill
, color
, shape
, linetype
, group
. Diese werden dazu benutzt, um den Stufen der Gruppierungsvariablen unterschiedliche Farben, Formen, Linien, etc. zuzuweisen.
In diesem Beispiel haben wir die Gruppierungsvariable geschlecht
und wir wollen, dass die beiden Stufen von geschlecht
verschiedene Farben haben und mit verschiedenen Farben “ausgefüllt” werden.
Wenn wir die “aesthetic mappings” innerhalb der Funktion ggplot()
definieren, gelten sie für alle “Layers”, d.h. für alle Elemente des Plots. Wir könnten diese mappings auch für jede “Layer” separat definieren.
<- stress |>
p ggplot(mapping = aes(
x = geschlecht,
y = stress_psychisch,
color = geschlecht,
fill = geschlecht
))
p
ist nun ein “leeres” Plot-Objekt. Wir können es uns anschauen, aber es wird noch nichts angezeigt, da es noch keine “Layers” enthält. Ein ggplot2
Objekt wird angezeigt, indem wir das Objekt auf der Konsole ausgeben lassen, entweder mit oder ohne print()
.
p
# oder print(p)
Wir sehen, dass ggplot2
für uns schon die Achsen anhand der Variablennamen beschriftet hat.
5.3 Schritt 3: geoms hinzufügen
Dem Plot-Objekt p
können wir nun mit geom_
Funktionen “Layers” hinzufügen. Die Syntax funktioniert so: Wir “addieren” zu dem Plot-Objekt p
ein geom
: p + geom_
.
5.3.1 Punktdiagramm
Wir versuchen zuerst, die Beobachtungen als Punkte darzustellen:
# die Funktion geom_point() hat ein size Argument
+ geom_point(size = 3) p
Die Punkte werden nun in verschiedenen Farben dargestellt, aber innerhalb eines Geschlechts werden Punkte eventuell übereinander geplottet, wenn sie denselben Wert haben (overplotting). Für diesen Fall gibt es die Funktion geom_jitter()
, welche Punkte mit einem “jittering’ nebeneinander zeichnet:
+ geom_jitter() p
geom_jitter()
hat ein Argument width
, mit dem wir bestimmen können, wie breit die Streuung der Punkte ist.
+ geom_jitter(width = 0.2) p
geom_jitter()
hat weitere Argumente: size
bestimmt den Durchmesser der Punkte, und alpha
bestimmt die Transparenz.
+ geom_jitter(width = 0.2, size = 4, alpha = 0.6) p
5.3.2 Verteilung grafisch darstellen
Eine weitere Möglichkeit wäre, die zentrale Tendenz und Streuung der Daten mit einem Boxplot- oder Violin-Diagramm darzustellen.
+ geom_boxplot() p
In einem Boxplot wird der Median dargestellt, das Rechteck repräsentiert die mittleren 50%, und die “whiskers” zeigen 1.5 * den Interquartilsbereich. Ausreisser werden mit Punkten dargestellt. Um den Median zu sehen, ist es besser, wenn wir das fill
Attribut weglassen:
<- stress |>
p ggplot(mapping = aes(
x = geschlecht,
y = stress_psychisch,
color = geschlecht
))
+ geom_boxplot() p
Ein Violin-Plot ist ähnlich wie ein Boxplot, zeigt aber nicht die Quantile, sondern ein “kernel density estimate”. Ein Violin-Plot sieht am besten aus, wenn wir das fill
Attribut verwenden.
<- stress |>
p ggplot(mapping = aes(
x = geschlecht,
y = stress_psychisch,
fill = geschlecht
))+ geom_violin() p
Wenn wir feststellen, dass ein Mapping nicht für alle “Layers” gelten soll, dann können wir es für jede “Layer” individuell definieren, anstatt in der ggplot()
Funktion:
<- stress |>
p ggplot(mapping = aes(
x = geschlecht,
y = stress_psychisch
))
+ geom_boxplot(mapping = aes(color = geschlecht)) p
# oder einfach
+ geom_boxplot(aes(color = geschlecht)) p
+ geom_violin(aes(fill = geschlecht)) p
5.3.3 Mehrere Layers kombinieren
Wir können auch mehrere “Layers” verwenden. Wir müssen lediglich mehrere geom_
Funktionen mit einem +
zusammenfügen:
+
p geom_violin(aes(fill = geschlecht)) +
geom_jitter(width = 0.2, alpha = 0.6)
In den bisherigen Beipielen haben wir kein Plot-Objekt erstellt, sondern den Datensatz mit dem pipe
Operator an die ggplot()
Funktion geschickt, und dann mit +
direkt die geoms
hinzugefügt. Ausserdem haben wir weitere Funktionen verwendet, wie z.B. theme_classic()
, um den Hintergrund weiss darzustellen.
|>
stress ggplot(mapping = aes(
x = geschlecht,
y = stress_psychisch,
fill = geschlecht
+
)) geom_violin() +
geom_jitter(width = 0.2, alpha = 0.6) +
theme_classic()
5.4 Geoms für verschiedene Datentypen
Wir fassen zusammen: bisher haben wir gelernt, dass wir einen Plot in mehreren Schritten zusammenstellen. Wir beginnen mit einem Dataframe und definieren mit der ggplot()
Funktion ein ggplot2
Objekt. Mit der aes()
Funktion weisen wir Variablen eines Dataframes der X-, bzw. der Y-Achse zu und definieren weitere “aesthetic mappings”, z.B. eine farbliche Codierung anhand einer Gruppierungsvariablen. Anschliessen fügen wir dem Plot-Objekt Grafikelemente mit geom_*
Funktionen als “Layers” hinzu.
Nun schauen wir uns eine Auswahl an geoms
für verschiedene Kombination von Variablen an. Wir können dabei entweder eine Variable auf der X-Achse oder zwei Variablen auf den X- und Y-Achsen darstellen und diese Variablen können entweder kontinuierlich oder kategorial sein.
Für die folgenden Beispiele verwenden wir die Datensätze beispieldaten
und kinderwunsch
:
<- read_sav("data/Kinderwunsch_Schweiz.sav")
kinderwunsch
<- kinderwunsch |>
kinderwunsch mutate(geschl = haven::as_factor(geschl))
5.4.1 Eine Variable
Wenn wir nur eine Variable auf der X-Achse grafisch darstellen möchten, müssen wir aber dennoch Werte auf der Y-Achse darstellen. Dies wird oft eine deskriptive Zusammenfassung wie z.B. Häufigkeiten sein.
Kategoriale Variablen
Wenn wir eine kategoriale Variable grafisch darstellen, verwenden wir oft einen bar chart or bar graph. Dieser stellt z.B. Häufigkeiten der verschiedenen Kategorien anhand eines Rechtecks (rectangular bar) dar. Die Funktion, welche dafür verwendet wird, heisst geom_bar()
.
Als Beispiel wollen wir die Häufigkeiten der vier Bildungsstufen des Vaters plotten.
<- beispieldaten |>
p select(bildung_vater) |>
drop_na() |>
ggplot(aes(x = bildung_vater))
+ geom_bar(fill = "lightblue", color = "black") p
Eine Übersicht über die möglichen Farbnamen erhalten Sie mit der Funktion colors()
. Es gibt 657 davon, wir zeigen hier mit sample(15)
nur 15 zufällig ausgewählte an:
colors() |> sample(15)
[1] "moccasin" "steelblue4" "bisque" "gray18"
[5] "grey61" "purple1" "orchid4" "grey80"
[9] "palegreen1" "darkslateblue" "green" "aquamarine3"
[13] "grey39" "slateblue" "tan3"
Auch hier können wir zusätzlich eine Gruppierungsvariable angeben, anhand derer wir die Rechtecke farblich kodieren.
<- beispieldaten |>
p select(bildung_vater, westost) |>
drop_na() |>
ggplot(aes(x = bildung_vater, fill = westost))
+ geom_bar() p
Standardmässig kreiert ggplot2
einen stacked Bar Chart, d.h. die Rechtecke werden aufeinander gestapelt. Wenn dies nicht erwünscht ist, können wir das Argument position = "dodge"
der Funktion geom_bar()
verwenden. Damit teilen wir mit, dass die Bars nebeneinander gezeichnet werden sollen.
+ geom_bar(position = "dodge") p
Als dritte Variante können wir position = "identity"
verwenden; so werden die Bars übereinander gezeichnet. Da das hintere Rechteck nicht mehr sichtbar ist, verwenden wir das alpha
Argument, um die Bars transparent zu machen.
+ geom_bar(position = "identity", alpha = 0.6) p
Kontinuierliche Variablen
Falls die Variable, welche wir grafisch darstellen wollen, nicht kategorial, sondern kontinuierlich ist, bietet sich ein Histogramm an; dies erzeugen wir mit der Funktion geom_histogram()
. Als Beispiel betrachten wir den psychischen Stress.
Ein Histogramm bietet eine grafische Darstellung der Verteilung einer numerischen Variablen. Dazu werden die Werte dieser Variablen in diskrete Intervalle, oder bins
, unterteilt. Auf der Y-Achse werden dann, analog zu einem Bar Chart, die Häufigkeiten in den jeweiligen Intervallen dargestellt. Die Bestimmung der Grösse der Intervalle (binwidth)
ist kritisch. Wenn wir nichts spezifieren, wählt ggplot2
selber eine binwidth
aus, aber wir können diese mit dem Argument binwidth
auch selber angeben.
<- beispieldaten |>
p select(stress_psychisch) |>
drop_na() |>
ggplot(mapping = aes(x = stress_psychisch))
# Wir lassen die binwidth automatisch auswählen
+ geom_histogram() p
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
# Wir bestimmen die binwidth selber
+ geom_histogram(binwidth = 0.5) p
Die Bestimmung der binwidth
hängt natürlich von der Skala der Variablen ab und sollte weder zu fein noch zu grob sein.
Wenn wir auf der Y-Achse anstelle der absoluten die relativen Häufigkeiten sehen wollen, können wir y = after_stat(density)
als Argument der aes()
Funktion verwenden.
<- beispieldaten |>
p select(stress_psychisch) |>
drop_na() |>
ggplot(mapping = aes(x = stress_psychisch, y = after_stat(density)))
+ geom_histogram(binwidth = 0.5) p
Selbsverständlich gibt es auch für Histogramme die Möglichkeit, eine Gruppierungsvariable zu verwenden.
<- beispieldaten |>
p select(stress_psychisch, geschlecht) |>
drop_na() |>
ggplot(mapping = aes(x = stress_psychisch, fill = geschlecht))
+ geom_histogram(binwidth = 0.5) p
Wie beim Bar Chart werden die Histogramme übereinander geplotted (“stacked”). Wollen wir sie aufeinander, verwenden wir position = "identity"
.
<- beispieldaten |>
p select(stress_psychisch, geschlecht) |>
drop_na() |>
ggplot(mapping = aes(x = stress_psychisch, fill = geschlecht))
+ geom_histogram(
p binwidth = 0.5,
position = "identity",
alpha = 0.6
)
Nebeneinander geht auch:
<- beispieldaten |>
p select(stress_psychisch, geschlecht) |>
drop_na() |>
ggplot(mapping = aes(x = stress_psychisch, fill = geschlecht))
+ geom_histogram(
p binwidth = 0.5,
position = "dodge"
)
5.4.2 Zwei Variablen
Nun stellen wir zwei Variablen eines Datensatzes gemeinsam dar. Auch hier hängen die möglichen geoms
vom Datentyp der Variablen ab.
X und Y kontinuierlich
Wenn beide Variablen kontinuierlich sind, können wir deren Zusammenhang anhand eines ‘Scatterplots’ oder eines Liniendiagrams darstellen. Wir verwenden die Funktionen geom_point()
, bzw. geom_line()
.
Als Beispiel wollen wir den Zusammenhang zwischen psychischem Stress und Lebenszufriedenheit visualisieren.
<- beispieldaten |>
p select(stress_psychisch, leben_gesamt) |>
drop_na() |>
ggplot(mapping = aes(x = stress_psychisch, y = leben_gesamt))
+ geom_point(size = 2, alpha = 0.6) p
Die size
und alpha
Argumente haben wir weiter oben bereits kennengelernt, sowie die Möglichkeit, ‘overplotting’ mit der Funktion geom_jitter()
zu vermeiden. Sowohl geom_jitter()
als auch geom_point()
haben auch eine colour
oder ein color
Argument.
+ geom_jitter(colour = "purple") p
Die Gruppierung anhand einer kategorialen Variablen funktioniert auch hier. Wir verwenden sowohl die Farbe als auch die Form der Punkte, um die Kategorien besser unterscheiden zu können.
<- beispieldaten |>
p select(stress_psychisch, leben_gesamt, geschlecht) |>
drop_na() |>
ggplot(mapping = aes(
x = stress_psychisch,
y = leben_gesamt,
color = geschlecht,
shape = geschlecht
))
+ geom_jitter(size = 3, alpha = 0.9) p
Mit der Funktion geom_line()
können wir Liniendiagramme erstellen. Als Beispiel wollen wir in einem neuen Dataframe die mittlere Schulnote für die verschiedenen Bildungsniveaus des Vaters berechnen, und dann grafisch darstellen. Bevor wir die durchschnittliche Note plotten, konvertieren wir den Faktor bildung_vater
zu einer numerischen Variable.
<- beispieldaten |>
bildung_vater select(Gesamtnote, bildung_vater) |>
drop_na() |>
group_by(bildung_vater) |>
summarize(Gesamtnote = mean(Gesamtnote)) |>
mutate(bildung_vater_num = as.numeric(bildung_vater))
bildung_vater
# A tibble: 4 × 3
bildung_vater Gesamtnote bildung_vater_num
<fct> <dbl> <dbl>
1 Hauptschule 4.05 1
2 Realschule 4.38 2
3 Abitur 4.50 3
4 Hochschule 4.69 4
<- bildung_vater |>
p ggplot(aes(
x = bildung_vater_num,
y = Gesamtnote
))
+ geom_line() p
Wir können nun wie im “Honeymoon oder Hangover”-Beispiel das Liniendiagramm um Punkte ergänzen:
+ geom_line() +
p geom_point(size = 4)
Auch geom_line()
hat Argumente, um die Eigenschaften zu ändern. In diesem Fall benützen wir das Argument linteype
, welches die Werte "blank", "solid", "dashed", "dotted", "dotdash", "longdash" oder "twodash"
anehmen kann.
+ geom_line(linetype = "dashed", linewidth = 2) +
p geom_point(size = 8)
X kategorial und Y kontinuierlich
Wenn eine der Variablen kategorial ist, können wir diese, anstatt sie als Gruppierungsvariable zu verwenden, auf einer Achse darstellen.
Beipiele dafür haben wir oben schon gesehen: dort haben wir die Variablen geschlecht
und psychischer Stress
dargestellt und die Funktionen geom_boxplot()
und geom_violin()
benutzt. Wir können aber auch die Funktion geom_bar()
für zwei Variablen verwenden. Die Variable auf der Y-Achse wird in diesem Fall für alle Beobachtungen in den Kategieren auf der X-Achse summiert. Da dies keine statistische Transformation benötigt, verwenden wir das Argument stat = 'identity'
.
Als Beispiel betrachten wir den Kinderwunsch-Datensatz. In diesem wurden Versuchspersonen gefragt, ob sie ein Kind wollen oder nicht (binäre Antwort). Zusätzlich wurden die Intimität zur eigenen Mutter, die emotionale Einstellung zu Kindern und das Geschlecht erhoben. Auf der Y-Achse stellen wir die absoluten Häufigkeiten einer “Ja”-Antwort dar.
<- kinderwunsch |>
p ggplot(aes(
x = geschl,
y = kind_d,
fill = geschl
))
+ geom_bar(stat = "identity") p
Um diese Grafik besser verstehen zu können, berechnen wir zusätzlich noch die relativen Häufigkeiten einer “Ja”-Antwort pro Geschlecht.
|>
kinderwunsch group_by(geschl) |>
summarize(
n = n(),
Ja = sum(kind_d),
prop_Ja = sum(kind_d) / n
)
# A tibble: 2 × 4
geschl n Ja prop_Ja
<fct> <int> <dbl> <dbl>
1 maennlich 44 30 0.682
2 weiblich 56 44 0.786
X und Y kategorial
Zuletzt können die Variablen sowohl auf der X- als auch auf der Y-Achse kategorial sein. In diesem Fall wäre es sinnvoll, die gemeinsamen Häufigkeiten grafisch darzustellen. Dafür gibt es die Funktion geom_count()
.
Als Beispiel wollen wir die gemeinsame Häufigkeitsverteilung der Bildung des Vaters und der Bildung der Mutter betrachten.
<- beispieldaten |>
p select(starts_with("bildung")) |>
drop_na() |>
ggplot(aes(
x = bildung_vater,
y = bildung_mutter
))
+ geom_count() p
geom_count()
zählt die gemeinsamen Häufigkeiten der Kategorien der beiden Variablen und stellt diese als Durchmesser der Punkte dar.
Beispiele
Wir betrachten nun 2 Übungsbeispiele.
Arbeitszufriedenheit
Im ersten Beispiel laden wir den Arbeitszufriedenheitsdatensatz vom letzten Kapitel nochmals und schauen uns die Grafik genauer an.
<- read_delim("data/honeymoon.csv",
honeymoon delim = ";"
)
Rows: 10 Columns: 4
── Column specification ────────────────────────────────────────────────────────
Delimiter: ";"
dbl (4): Firma, Anfang, Drei_Monate, Sechs_Monate
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# Wiederholung vom letzten Kapitel:
<- honeymoon |>
honeymoon_long_bedingung mutate(
Firma = as_factor(Firma),
ID = row_number()
|>
) pivot_longer(!c(Firma, ID),
names_to = "Messzeitpunkt",
values_to = "Arbeitszufriedenheit"
|>
) mutate(Messzeitpunkt = factor(Messzeitpunkt)) |>
arrange(Firma, ID) |>
group_by(Firma, ID) |>
mutate(Personenmittelwert = mean(Arbeitszufriedenheit)) |>
group_by(Firma, Messzeitpunkt) |>
summarize(Bedingungsmittelwert = mean(Arbeitszufriedenheit))
`summarise()` has grouped output by 'Firma'. You can override using the
`.groups` argument.
honeymoon_long_bedingung
# A tibble: 6 × 3
# Groups: Firma [2]
Firma Messzeitpunkt Bedingungsmittelwert
<fct> <fct> <dbl>
1 1 Anfang 9
2 1 Drei_Monate 5
3 1 Sechs_Monate 7
4 2 Anfang 10
5 2 Drei_Monate 10.8
6 2 Sechs_Monate 11
Wir stellen nun anhand eines Liniendiagrams die mittlere Arbeitszufriedenheit über die Messzeitpunkte hinweg dar, und zwar benützen wir als Gruppierungsfaktor die Firma
. group = Firma
ist hier wichtig, die anderen beiden Argumente, color = Firma
und linetype = Firma
sind nur aus ästhetischen Gründen da und könnten weggelassen werden.
<- honeymoon_long_bedingung |>
p ggplot(aes(
x = Messzeitpunkt,
y = Bedingungsmittelwert,
color = Firma,
linetype = Firma,
group = Firma
))
+ geom_point(size = 4) +
p geom_line(linewidth = 2)
Liniendiagramme werden oft benutzt, um den zeitlichen Verlauf einer Variablen darzustellen. Dies bedeutet, dass wir auf der X-Achse die Zeit darstellen, wie in diesem Beispiel. Meistens wird Zeit jedoch als kontinuierliche Variable verwendet und nicht, wie hier, als Faktor.
Wide vs. Long: Bildung der Eltern
Anhand des nächsten Beipiels betrachten wir den Unterschied zwischen dem long und dem wide Format. Wir haben, als wir die gemeinsame Häufigkeitsverteilung der Bildung des Vaters und der Mutter dargestellt haben, bildung_vater
und bildung_mutter
als separate Variablen verwendet, um sie auf separaten Achsen darzustellen. Wir könnten jedoch auch bildung_vater
und bildung_mutter
als Stufen eines Messwiederholungsfaktors eltern
(key
) zusammenfassen, und die Bildungsniveaus als Messvariable bildung
(value
), d.h. als key
/value
Paar. Dies machen wir, wenn wir bildung
als Variable auf einer Achse verwenden wollen und eltern
als Gruppierungsvariable.
Dies ist vielleicht nicht ganz einfach zu verstehen, deshalb betrachten wir gleich ein konkretes Beispiel. Wir wollen nun, ähnlich wie oben, die mittlere Schulnote für die verschiedenen Bildungsniveaus der Eltern grafisch darstellen. Diesmal machen wir dies für beide Elternteile. Wir wollen jedoch unterschiedliche Linien für Vater und Mutter. Nun ist es wichtig, dass wir einen long Datensatz bilden.
<- beispieldaten |>
bildung # Variablen auswählen
select(Gesamtnote, bildung_vater, bildung_mutter) |>
# Fehlende Werte ausschliessen
drop_na() |>
# wide zu long
pivot_longer(!Gesamtnote, names_to = "eltern", values_to = "bildung") |>
# Präfix bildung_ bei eltern-Variable entfernen
mutate(eltern = str_replace(eltern, ".*_", "")) |>
# zu Faktoren konvertieren
mutate(
eltern = factor(eltern, levels = c("mutter", "vater")),
bildung = factor(bildung, levels = c(
"Hauptschule", "Realschule",
"Abitur", "Hochschule"
))|>
) # Gruppieren: zuerst Eltern, dann Bildungsniveaus
group_by(eltern, bildung) |>
# Mittlere Note berechnen
summarize(Gesamtnote = mean(Gesamtnote))
`summarise()` has grouped output by 'eltern'. You can override using the
`.groups` argument.
bildung
# A tibble: 8 × 3
# Groups: eltern [2]
eltern bildung Gesamtnote
<fct> <fct> <dbl>
1 mutter Hauptschule 4.10
2 mutter Realschule 4.37
3 mutter Abitur 4.51
4 mutter Hochschule 4.73
5 vater Hauptschule 4.08
6 vater Realschule 4.38
7 vater Abitur 4.50
8 vater Hochschule 4.69
<- bildung |>
p ggplot(aes(
x = bildung,
y = Gesamtnote,
colour = eltern,
linetype = eltern,
group = eltern
))
+ geom_line(linewidth = 2) +
p geom_point(size = 4)
5.5 Facets
Bisher haben wir Gruppierungsvariablen dazu benutzt, um unterschiedliche Farben/Formen/Linien für die Kategorien der Gruppierungsvariable innerhalb eines Plots zu erzeugen. Manchmal ist dies jedoch zu unübersichtlich.
Wollen wir zum Beispiel ein Histogram der Schulnoten erstellen, und zwar für jede Stufe der Bildung der Mutter, dann wäre die Grafik völlig überladen.
<- beispieldaten |>
p select(Gesamtnote, bildung_mutter) |>
drop_na() |>
ggplot(mapping = aes(
x = Gesamtnote,
fill = bildung_mutter
))
+ geom_histogram(
p binwidth = 0.8,
position = "dodge"
)
Eine offensichtliche Lösung wäre, die Histogramme für die Bildungsniveaus der Mutter in separaten Grafiken darzustellen.
Genau dies können wir mit den Funktionen facet_wrap()
und facet_grid()
machen.
Mit facet_wrap()
erstellen wir so eine Grafik für jede Kategorie der Gruppierungsvariable:
<- beispieldaten |>
p select(Gesamtnote, bildung_mutter) |>
drop_na() |>
ggplot(mapping = aes(
x = Gesamtnote,
fill = bildung_mutter
+
)) facet_wrap(~bildung_mutter)
+ geom_histogram(binwidth = 0.8) p
Wenn wir zwei Gruppierungsvariablen haben, können wir mit facet_grid()
ein Raster erzeugen.
<- beispieldaten |>
p select(Gesamtnote, bildung_mutter, bildung_vater) |>
drop_na() |>
ggplot(mapping = aes(x = Gesamtnote)) +
facet_grid(bildung_mutter ~ bildung_vater)
+ geom_histogram(
p binwidth = 0.8,
fill = "steelblue4"
)
Hier werden die Stufen von bildung_mutter
in den Zeilen dargestellt, die Stufen von bildung_vater
in den Spalten.
Als zweites Beispiel können wir den Notenschnitt in Abhängigkeit der Bildung der Eltern als Liniendiagram darstellen, und zwar in separaten Plots für Väter und Mütter getrennt. Anhand dieses Beispiels sehen wir, dass wir facet_grid()
auch dann verwenden können, wenn wir nur eine Gruppierungsvariable haben, und zwar um die Anzahl Zeilen bzw. Spalten festzulegen.
Wenn wir die Gruppierung in den Zeilen haben wollen, schreiben wir facet_grid(Gruppierungsvariable ~ .)
, wenn sie in den Spalten wollen, schreiben wir facet_grid(. ~ Gruppierungsvariable)
. Der Punkt .
bedeutet hier, dass wir für die Zeilen/Spalten keine Gruppierungsvariable verwenden.
<- bildung |>
p ggplot(aes(
x = bildung,
y = Gesamtnote,
group = eltern
))
+ geom_line(linewidth = 2, color = "pink") +
p geom_point(size = 4, color = "steelblue3") +
# Stufen von 'eltern' in die Zeilen
facet_grid(eltern ~ .)
<- bildung |>
p ggplot(aes(
x = bildung,
y = Gesamtnote,
group = eltern
))
+ geom_line(linewidth = 2, color = "pink") +
p geom_point(size = 4, color = "steelblue3") +
# Stufen von 'eltern' in die Spalten
facet_grid(. ~ eltern)
5.6 Farben und Themes
Bisher hat ggplot2
automatisch für uns Farben gewählt, wenn wir Farben für eine Gruppierung verlangt haben. Die Standard Farbpalette ist jedoch für Farbenblinde äusserst schlecht geeignet. Es gibt viele Farbpaletten, welche wir verwenden könnten.
Wir definieren hier jedoch eine eigene, für Farbenblinde geeignete Farbpalette.
<- c(
palette "#000000", "#E69F00",
"#56B4E9", "#009E73",
"#F0E442", "#0072B2",
"#D55E00", "#CC79A7"
)
Wir definieren hier also einen Vektor von acht Hex Codes. Folglich dürfte unsere Gruppierungsvariable nicht mehr als acht Kategorien haben.
Die Palette verwenden wir so:
- um Formen auszufüllen, verwenden wir
scale_fill_manual(values = palette)
- für Linien und Punkte verwenden wir:
scale_colour_manual(values = palette)
Als Beispiel plotten wir nochmals den Zusammenhang zwischen stress_psychisch
und leben_gesamt
, diesmal mir unserer Farbpalette.
<- beispieldaten |>
p select(stress_psychisch, leben_gesamt, geschlecht) |>
drop_na() |>
ggplot(mapping = aes(
x = stress_psychisch,
y = leben_gesamt,
color = geschlecht,
shape = geschlecht
))
+ geom_jitter(size = 3, alpha = 0.9) +
p scale_colour_manual(values = palette)
Wir könnten die Farben auch so ‘von Hand’ bestimmen:
+ geom_jitter(size = 3, alpha = 0.9) +
p scale_colour_manual(values = c("pink2", "steelblue3"))
Ein weiterer heikler Punkt ist der graue Hintergrund, den ggplot2
automatisch wählt. Diesen können wir am einfachsten ändern, indem wir ein theme
definieren. Es gibt zwei solcher themes
, welche einen weissen Hintergrund haben: theme_bw()
und theme_classic()
. Diese unterscheiden sich darin, dass theme_classic()
keine grid lines zeichnet, sondern nur die linke und die untere Achse.
<- beispieldaten |>
p select(stress_psychisch, leben_gesamt, geschlecht) |>
drop_na() |>
ggplot(mapping = aes(
x = stress_psychisch,
y = leben_gesamt,
color = geschlecht,
shape = geschlecht
))
+ geom_jitter(size = 3, alpha = 0.9) +
p scale_colour_manual(values = palette) +
theme_bw()
<- beispieldaten |>
p select(stress_psychisch, leben_gesamt, geschlecht) |>
drop_na() |>
ggplot(mapping = aes(
x = stress_psychisch,
y = leben_gesamt,
color = geschlecht,
shape = geschlecht
))
+ geom_jitter(size = 3, alpha = 0.9) +
p scale_colour_manual(values = palette) +
theme_classic()
5.7 Beschriftungen
Wir können nun auch noch mit xlab()
und ylab()
die Beschriftungen der X/Y-Achsen ändern, und mit der Funktion ggtitle()
dem Plot einen Titel geben. Mit der Funktion labs()
können wir zusätzlich noch den Titel der Legende ändern.
Zuletzt wollen wir auch die Schriftgrösse ändern, da die Standardgrösse oft zu klein erscheint. Dies erreichen wir mit dem Argument base_size = SCHRIFTGRÖSSE)
der theme_*
Funktionen.
<- beispieldaten |>
p select(stress_psychisch, leben_gesamt, geschlecht) |>
drop_na() |>
ggplot(mapping = aes(
x = stress_psychisch,
y = leben_gesamt,
color = geschlecht,
shape = geschlecht
))
+ geom_jitter(size = 3, alpha = 0.9) +
p scale_colour_manual(values = palette) +
theme_classic(base_size = 14) +
ggtitle("Zusammenhang zwischen Stress und Zufriedenheit") +
xlab("Psychischer Stress") +
ylab("Zufriedenheit") +
# Titel der color- und shape-Legende ist "Geschlecht"
labs(
color = "Geschlecht",
shape = "Geschlecht"
)
5.8 Grafiken speichern
Wenn wir eine schöne Grafik erstellt haben, wollen wir sie natürlich speichern. Dies können wir mit der Funktion ggsave()
machen. Die Funktion nimmt als Argumente den Dateinamen, den Namen des Plot Objekts und weitere Eigenschaften, wie die gewünschte Höhe und Breite des Plots. Diese können z.B. in “cm” angebenen werden, mit dem Argument units = "cm"
. Um die Grafik zu speichern, müssen wir also unser fertiges ggplot2
Objekt einer Variablen zugewiesen haben:
<- beispieldaten |>
p select(stress_psychisch, leben_gesamt, geschlecht) |>
drop_na() |>
ggplot(mapping = aes(
x = stress_psychisch,
y = leben_gesamt,
color = geschlecht,
shape = geschlecht
))
# Wir nennen die Grafik 'my_plot'
<- p + geom_jitter(size = 3, alpha = 0.9) +
my_plot scale_colour_manual(values = palette) +
theme_classic(base_size = 14) +
ggtitle("Zusammenhang zwischen Stress und Zufriedenheit") +
xlab("Psychischer Stress") +
ylab("Zufriedenheit") +
labs(
color = "Geschlecht",
shape = "Geschlecht"
)
my_plot
kann nun gespeichert werden:
ggsave(
filename = "my_plot.png",
plot = my_plot
)
Die Grafik kann auch in den Formaten eps, ps, tex, pdf, jpeg, tiff, svg und wmf gespeichert werden. Dazu muss lediglich die Endung .png
ersetzt werden, beispielsweise durch .pdf
. Je nach Anwendungszweck lohnt es sich, auf ein anderes Dateiformat zu setzen. Insbesondere wenn die Grafiken vergrössert werden sollen, lohnt es sich, auf ein Vektorgrafikformat wie .svg
oder .wmf
zu setzen.
5.9 Übungsaufgabe
In dieser Übungsaufgabe wollen wir die sechs Selbstwirksamkeitsskalen im beispieldaten
Datensatz untersuchen. Wir gehen davon aus, dass diese in einem Zusammenhang mit dem Gesamtnotenschnitt stehen. Bevor wir eine multiple Regression rechnen, wollen wir versuchen, Zusammenhänge zwischen diesen Variable grafisch darstellen.
<- beispieldaten |>
selbstwirksamkeit_wide select(ID, Gesamtnote, starts_with("swk_")) |>
drop_na()
selbstwirksamkeit_wide
# A tibble: 279 × 8
ID Gesamtnote swk_neueslernen swk_lernregulation swk_motivation
<dbl> <dbl> <dbl> <dbl> <dbl>
1 2 4 5 4 4.6
2 10 5 5 4.88 6
3 11 4 4.57 5.38 5.4
4 12 5 5.33 5.29 4.67
5 14 4 4.86 4.5 4.6
6 15 4 4 4.38 5.6
7 16 5 4.83 6.25 5
8 17 4 6.14 5.62 6
9 18 4 5.14 4.62 4.4
10 19 4 5.43 4.62 5.2
# ℹ 269 more rows
# ℹ 3 more variables: swk_durchsetzung <dbl>, swk_sozialkomp <dbl>,
# swk_beziehung <dbl>
Versuchen Sie, Zusammenhänge zwischen den sechs Selbstwirksamkeitsskalen zu entdecken, indem Sie diese grafisch darstellen. Versuchen Sie zum Beispiel, für jedes Variablenpaar einen Scatterplot (Punktdiagram) zu erstellen.