Tutorials vom Statistik Support, Institut für Psychologie, WWU Münster

Homepage des Supports


Auf dieser Seite möchte ich Ihnen die Grund- und Vorzüge des Grafikpakets ggplot2 von Hadley Wickham näherbringen. Das Paket basiert auf der sogenannten Grammar of Graphics von Wilkinson und Kollegen (mehr dazu). Vereinfacht gesagt ist das Ziel dieser “Grammatik”, die Elemente (Variablen, Achsen, Legenden, Darstellungsformen…) einer Datengrafik möglichst logisch strukturiert zu beschreiben. Basierend auf dieser Struktur bietet ggplot2 ein sehr flexibles Grafiksystem, mit dem sich auch komplexe Zusammenhänge mit wenigen Ausdrücken darstellen lassen. Trotzdem sind die Funktionen des Pakets auch für Einsteiger leicht zugänglich.

Ziel dieses Tutorials ist es, das Grundprinzip der ggplots zu verstehen und einige einfache Manipulationen vorzunehmen. In weiteren Tutorials werden dann noch weitere Darstellungsvarianten und feinere Manipulationsmöglichkeiten vorgestellt.

Für unsere Plots benötigen wir natürlich zunächst Daten. Die erstellen wir uns hier einfach selber.

# Sämtliche R-Code-Blöcke wie diesen hier können Sie einfach kopieren bzw. selbst in ein R-Skript eingeben und dann ausführen

df <- data.frame(IQ = rnorm(100, 100, 15), Groesse = rnorm(100, 175, 9), Anzahl_Kinder = sample(0:5, 100, replace = TRUE), Nation = rep(c("Gallier","Römer"), each = 50))

Wie der Befehl zum Erstellen der Tabelle genau funktioniert, braucht uns an dieser Stelle nicht zu interessieren1. Wir können jedoch prüfen, wie die Tabelle nun aufgebaut ist, indem wir uns die ersten sechs Zeilen ausgeben lassen:

head(df)
##          IQ  Groesse Anzahl_Kinder  Nation
## 1 124.34572 163.9950             3 Gallier
## 2 108.14958 172.3603             5 Gallier
## 3 102.89557 171.2969             1 Gallier
## 4  95.27616 163.1366             4 Gallier
## 5 107.63225 159.4098             4 Gallier
## 6 107.08360 153.5915             4 Gallier

Wir können uns auch noch die Struktur der Tabelle genauer anschauen:

str(df)
## 'data.frame':    100 obs. of  4 variables:
##  $ IQ           : num  124.3 108.1 102.9 95.3 107.6 ...
##  $ Groesse      : num  164 172 171 163 159 ...
##  $ Anzahl_Kinder: int  3 5 1 4 4 4 4 1 3 0 ...
##  $ Nation       : Factor w/ 2 levels "Gallier","Römer": 1 1 1 1 1 1 1 1 1 1 ...

Vor allem der str()-Befehl bietet eine gute Übersicht:

Für ggplot wie auch generell für R ist es von Vorteil, wenn die Datentabelle im “tidy data”-Format vorliegt, wenn also jede Beobachtung (auch jede Messwiederholung2) in einer eigenen Zeile steht (mehr zu “tidy data”; Wie kann ich meine Tabelle umstrukturieren). In unserem Fall liegen keine Messwiederholungen vor und wir können mit den Daten direkt weiterarbeiten.

Für dieses Tutorial wollen wir den Zusammenhang zwischen IQ und Körpergröße plotten. Dafür benutzen wir erst ein Mal die plot()-Funktion (diese Funktion ist euch eventuell schon geläufig). Das auf plot() beruhende Grafiksystem wird auch base graphics genannt, da es im Basis-R schon enthalten ist. Wir geben einfach die zwei zu plottenden Variablen an:

plot(df$Groesse, df$IQ)

Wie man sieht, erhalten wir einen einfachen Scatterplot mit kleinen Kreisen. Der Plot zeigt eine typische Eigenschaft von R: R-Funktionen versuchen oft, den je nach Input am besten passenden Output zu liefern. Da zwei numerische Variablen zu plotten sind, wird automatisch ein Scatterplot gewählt.

Jetzt erstellen wir zum Vergleich den gleichen Plot mit dem Paket ggplot2. Wir laden zunächst das Paket und definieren dann den Plot:

library("ggplot2")
# Mein erster ggplot:
ggplot(df, aes(x = Groesse, y = IQ)) + geom_point()

Das Prinzip ist bei ggplot2 offensichtlich anders als bei plot(): Es gibt eine ggplot()-Klammer, in der als erstes bestimmt wird, welche Tabelle dem Plot zugrundeliegen soll. Als nächstes gibt es innerhalb der ggplot2()-Klammer noch die sogenannte Aesthetics-Klammer (aes()), in der nun als zweites definiert wird, welche die zu plottenden x- und y-Variablen sein sollen. Nachdem die Basisinfos für den Plot in der ggplot()-Klammer definiert wurden, bestimmen wir als drittes, mit welchem geometrischen Element (geom) wir die Daten plotten möchten. In ggplot2 überlassen wir es also nicht unserer Funktion zu entscheiden, welche Art von Grafik wir haben möchten, sondern entscheiden dies selbst. Die Eingabe der zu plottenden Variablen (in der aes()-Klammer) wird separat definiert von der Art und Weise, wie die Daten dargestellt werden sollen (die Geoms).

Um einen ähnlichen Scatterplot wie zuvor zu definieren, legen wir also Groesse als x-Variable und IQ als y-Variable fest. Außerdem sollen die Daten als Punkte dargestellt werden (+ geom_point()). Das + drückt aus, dass die Punkte sozusagen als zusätzliche Schicht (engl. layer) auf den zuvor definierten Plot “aufgetragen” werden. Diese Ausdrucksweise ist typisch für ggplot2: Zusätzliche Elemente und Änderungen am Plot werden der Plotdefinition durch eine Verkettung von + xyz()-Ausdrücken hinzugefügt.

## Warning: package 'ggplot2' was built under R version 3.2.3

Wie man sieht, ist der Plot schon etwas übersichtlicher, er enthält Gitterlinien, die beim Ablesen der Datenpunkte helfen, und die Achsen sind jetzt mit den richtigen Variablennamen beschriftet. Praktischerweise kann man diese Grafik nun sehr leicht bearbeiten und erweitern. Als erstes probieren wir ein paar einfache Änderungen aus. Wir verändern innerhalb der geom_point-Klammer über die Parameter size, color und shape das Erscheinungsbild der Punkte. In der Hilfe zu geom_point (aufzurufen über ?geom_point) finden Sie unter Aesthetics alle Eigenschaften, die sich bei den Punkten verändern lassen.

# 2. ggplot 
ggplot(df, aes(x = Groesse, y = IQ)) + geom_point(size = 4, color = "blue", shape = 4)

Ein großer Vorteil von ggplot ist, dass wir diese Eigenschaften nicht nur manuell festlegen können, sondern sie auch problemlos auf eine dritte Variable “mappen” können. Dies geschieht wie auch die Zuweisung als x- oder y-Variable innerhalb der aes-Klammer.

Im nächsten Plot werden wir das ausprobieren, indem wir die Datenpunkte der “Gallier” und “Römer” in unterschiedlichen Farben darstellen lassen. Dazu muss einfach nur in der Aesthetics-Klammer angegeben werden, dass Nation eine weitere zu berücksichtigende Variable sein soll und dass sie über die Farbe der Grafikelemente repräsentiert sein soll. Das geht so: color = Nation. color ist nun also neben x und y eine weitere Daten-Dimension des Plots. In der geom_point()-Klammer muss die explizite Farbangabe color = "blue" jetzt wieder entfernt werden, weil diese sonst unser gewünschtes Mapping überschreiben würde.

# ggplot 3a
ggplot(df, aes(x = Groesse, y = IQ, color = Nation)) + geom_point(size = 4)

Voilà, die zwei Nationen sind in gut unterscheidbaren Farben dargestellt. Wie Sie sehen können, wird auch automatisch eine Legende mit ausgegeben.

Je nach Variable bieten sich andere Aesthetics (Farbe, Größe, Form, etc.) für das Mapping an. Um z.B. für jede Person darzustellen, wie viele Kinder sie hat, macht ein Mapping auf die Punktgröße Sinn, um die quantitative Information zu repräsentieren:

# ggplot 3b
ggplot(df, aes(x = Groesse, y = IQ, size = Anzahl_Kinder)) + geom_point()

Wir können in ggplot2 auch sehr einfach eine Regressionsgerade hinzufügen. Dazu fügen wir unserem Scatterplot ein weiteres Geom als zusätzlichen Layer hinzu. Das nötige Geom nennt sich smooth und ist eine Zusammenfassungslinie für Scatterplots. Wenn wir "lm" als Glättungsmethode wählen, entspricht dies der Regressionsgeraden (lm steht für linear model). Das probieren wir jetzt für unseren Plot 3a aus:

# 4. ggplot
ggplot(df, aes(x = Groesse, y = IQ, color = Nation)) + geom_point(size = 4) + geom_smooth(method = "lm")

Hier sehen Sie noch mal, dass die Angaben in der Aesthetics-Klammer auf alle Geoms angewendet werden. color = Nation wirkt sich daher auch auf das geom_smooth aus: Entsprechend der Anzahl der Faktorstufen in Nation werden zwei Geraden geplottet, die auch passend eingefärbt sind. Standardmäßig wird beim geom_smooth auch automatisch ein Konfidenzintervall für die Geradensteigung mitgeplottet. So erhält der Betrachter gleich eine zusätzliche Information über die Stärke des Zusammenhangs (das Intervall lässt sich mit se = FALSE ausblenden). Schließlich fällt noch auf, dass auch die Legende automatisch angepasst wurde, sodass sie jetzt beide Geoms widerspiegelt.


Übung

In dieser Übung können Sie noch weitere Änderungen an den obigen Plots vornehmen, um das Prinzip der ggplots noch besser zu verstehen.


Fußnoten


  1. Na gut, hier eine kurze Erläuterung: mit data.frame kann man mehrere Vektoren gleicher Länge zu einer Tabelle zusammenfassen. rnorm ist ein R-Befehl, mit dessen Hilfe wir Stichproben aus einer Normalverteilung ziehen können. Der erste Wert gibt die Anzahl der gewünschten Beobachtungen an. Mit dem zweiten und dritten Wert legen wir den Mittelwert und die Standardabweichung der Populationsverteilung fest, aus der wir die Stichprobe ziehen. sample ist ein Befehl, um aus einem Vektor eine zufällige Stichprobe zu ziehen. Der Vektor besteht hier aus den Zahlen 0 bis 5, als Anzahl der zu ziehenden Werte ist 100 angegeben. Außerdem ist angegeben, dass jedes Element aus dem Vektor mehrfach gezogen werden darf (replace = TRUE). rep ist ein Befehl, um einen Vektor mehrfach zu wiederholen (repeat). Hier soll der Vektor c("Gallier","Römer") wiederholt werden, genauer gesagt jedes Element des Vektors 50 mal (each = 50). Das Ergebnis ist also eine normalverteilte Variable IQ, eine normalverteilte Variable Größe, eine Variable Anzahl_Kinder mit ganzzahligen Werten und eine Variable Nation, die 50 mal den Textstring "Gallier" und 50 mal den Textstring "Römer" enthält.

  2. Zum Vergleich: In SPSS stehen Messwiederholungen für dieselbe Versuchsperson üblicherweise in derselben Zeile, aber in getrennten Spalten.