-
Notifications
You must be signed in to change notification settings - Fork 1
Grafiken
Grafiken spielen eine wichtige Rolle bei der Auswertung und Aufbereitung von psychologischen Experimenten. Sie helfen uns zum Einen komplizierte Zusammenhänge und Sachverhalte verständlich darzustellen, wenn wir Ergebnisse von Studien z.B. in wissenschaftlichen Artikeln, präsentieren und erklären möchten. Zum Anderen können uns Grafiken aber schon vor der Anwendung inferenzstatistischer Testverfahren Hinweise und Ideen dafür liefern, wie die von uns erhobenen Variablen zusammenhängen.
R bietet mit dem Erweiterungspaket ggplot2 eine umfangreiche Bibliothek zur Erstellung von Grafiken. Dabei reicht die Bandbreite von sehr einfachen und schnell zu erstellenden Grafiken bis zur vollständigen Anpassung aller Aspekte einer Grafik auf die eigenen Bedürfnisse, welche zwar mit deutlich höherem Aufwand aber ansonsten ohne Probleme auch bei sehr komplexen Grafiken durchführbar ist. Wir beginnen diese Einführung mit einfachen Beispielen und erweitern unsere Grafiken Schritt für Schritt mit neuen Aspekten und Einstellungsmöglichkeiten.
Zunächst muss ggplot2 installiert werden, falls dies noch nicht passiert ist. Wenn das Paket installier ist erfolgt die Einbindung der Bibliothek mit dem dafür üblichen Befehl:
install.packages("ggplot2") # Muss nur einmal ausgeführt werden, falls das Paket noch nicht installiert ist
library(ggplot2) # Zur Einbindung von ggplot2 in das folgende R-Skript
Die folgenden Beispiele basieren auf dem Datensatz mtcars, welcher als Beispieldatensatz bereits in R integriert ist. Dabei handelt es sich um eine Aufstellung verschiedener PKW und diverser technischer Daten wie Benzinverbrauch, Motorstärke, Fahrzeuggewicht, usw.:
mtcars
## mpg cyl disp hp drat wt qsec vs am gear carb
## Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
## Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
## Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
## Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
## Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
## Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4
## Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
## Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
## Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
## Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4
## Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3
## Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3
## Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
## Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4
## Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
## Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
## Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
## Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2
## Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1
## Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
## Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2
## AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2
## Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4
## Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
## Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
## Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
## Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
## Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
## Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
## Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
## Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
Weitere Informationen zu diesem Datensatz und den enthaltenen Variablen erhält man, wenn man die Hilfe zum Datensatz abruft. Die Hilfedatei wird in R-Studio im Bildschirmbereich unten rechts angezeigt:
help(mtcars)
Ein wichtiges Beispiel für den sinnvollen Einsatz von Grafiken stellen Streudiagramme (engl. scatter plot) bei Regressionsanalysen dar. Die in Streudiagrammen dargestellten Punktwolken vermitteln uns einen Hinweis darauf, ob ein Zusammenhang zwischen zwei Variablen besteht und wie dieser genau aussehen könnte.
ggplot2 stellt uns für das schnelle Erzeugen von Diagrammen die Funktion qplot() zur Verfügung. Mit Hilfe von qplot() lassen sich Streudiagramme sehr schnell und einfach erzeugen. Die Funktion benötigt hierzu lediglich die beiden Variablen, die auf der X- und Y-Achse gegeneinander abgetragen werden sollen sowie den Datensatz, der die entsprechenden Variablen enthält. Wir tragen nun die Motorleistung (X-Achse) gegen den einen Indikator für den Benzinverbrauch (Y-Achse) ab:
qplot(x = mtcars[, 4], y = mtcars[, 1], data = mtcars)
Um die Grafik für den Betrachter verständlicher zu gestalten, erweitern wir die Funktion um Argumente für die Beschriftungen der X- und Y-Achse (xlab und ylab) sowie für die Grafiküberschrift (main):
qplot(x = mtcars[, 4], y = mtcars[, 1], data = mtcars, xlab = "Motorstärke (PS)",
ylab = "Benzinverbrauch bzw. Reichweite (Miles/Gallon)", main = "Reichweite in Abhängigkeit der Motorstärke")
Das Streudiagramm erweckt beim Betrachten den (nicht überraschenden) Eindruck, dass die Reichweite, die ein Fahrzeug mit einer Gallone Benzin erzielt, abnimmt je mehr PS ein Fahrzeug hat, d.h. je stärker seine Motorleistung ist. Um diesen Eindruck zu überprüfen führen wir eine Regressionsanalyse für eine einfache lineare Regression durch:
reg <- lm(formula = mtcars[, 1] ~ mtcars[, 4], data = mtcars)
summary(reg)
##
## Call:
## lm(formula = mtcars[, 1] ~ mtcars[, 4], data = mtcars)
##
## Residuals:
## Min 1Q Median 3Q Max
## -5.712 -2.112 -0.885 1.582 8.236
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 30.0989 1.6339 18.42 < 2e-16 ***
## mtcars[, 4] -0.0682 0.0101 -6.74 1.8e-07 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 3.86 on 30 degrees of freedom
## Multiple R-squared: 0.602, Adjusted R-squared: 0.589
## F-statistic: 45.5 on 1 and 30 DF, p-value: 1.79e-07
Wir sehen, dass die Motorleistung (mtcars[,4]) in unserem Datensatz ein signifikanter Prädiktor für die Reichweite (mtcars[,1]) eines Fahrzeugs ist. Sowohl der Test für die gesamte Regressionsgleichung als auch für den einzelnen Prädiktor fallen hoch signifikant aus.
Wir können uns dieses Ergebnis zusätzlich grafisch veranschaulichen, in dem wir unsere bisherige Grafik um eine Regressionsgerade erweitern. Dazu lässt sich die Funktion qplot() um die Funktion geom_smooth() erweitern, die auf Basis des soeben genutzten lm() Befehls eine Regressionsgerade errechnet und darstellt:
qplot(x = mtcars[, 4], y = mtcars[, 1], data = mtcars, xlab = "Motorstärke (PS)",
ylab = "Benzinverbrauch bzw. Reichweite (Miles/Gallon)", main = "Reichweite in Abhängigkeit der Motorstärke") +
geom_smooth(method = "lm", se = FALSE, formula = y ~ x)
Die Funktion geom_smooth() unterstützt eine Reihe von Argumenten, darunter method zur Auswahl der Vorhersagefunktion (Wir wählen 'lm'), se zur Anzeige eines Konfidenzintervalls (Standardwert ist TRUE, aber wir verzichten zunächst darauf und setzen das Argument auf FALSE), sowie formula zur Anpassung der Regressionsgleichung (Standardwert ist y~x, welchen wir zunächst so beibehalten). Wir werden im Folgenden auf einige dieser Parameter weiter eingehen.
Vergleicht man die Ergebnisse der vorangegangenen Regressionsanalyse mit der errechneten Grafik, kann leicht der Eindruck enstehen, dass die angezeigte Linie nicht zu dem errechneten Y-Achsenabschnitt (Intercept) passt. Dieser ist laut Regressionsanalyse bei 30.1, scheint aber in der Grafik deutlich unter diesem Wert zu liegen. Das Problem besteht hier im angezeigten Bereich der X-Achse. ggplot2 bestimmt automatisch anhand der vorhandenen Daten einen geeigneten Anzeigebereich für jede Grafik. Dies kann aber auch irreführend sein bzw. die Vergleichbarkeit verschiedener Grafiken einschränken (wegen ungleicher Anzeigebereiche). Deshalb gibt es in der qplot() Funktion auch Argumente für die angezeigten Wertebereiche der X- und der Y-Achse (xlim und ylim). Dabei müssen hier jeweils Vektoren aus zwei Zahlen (für die Unter- und die Obergrenze) übergeben werden:
qplot(x = mtcars[, 4], y = mtcars[, 1], data = mtcars, xlab = "Motorstärke (PS)",
ylab = "Benzinverbrauch bzw. Reichweite (Miles/Gallon)", main = "Reichweite in Abhängigkeit der Motorstärke",
xlim = c(0, 350), ylim = c(0, 35)) + geom_smooth(method = "lm", se = FALSE,
formula = y ~ x)
Nun sehen wir, dass die angezeigte Linie sich auf den Bereich der vorhandenen Datenpunkte beschränkt. Die Linie lässt sich mit Hilfe des fullrange Arguments auch für den kompletten angezeigten Wertebereich anzeigen:
qplot(x = mtcars[, 4], y = mtcars[, 1], data = mtcars, xlab = "Motorstärke (PS)",
ylab = "Benzinverbrauch bzw. Reichweite (Miles/Gallon)", main = "Reichweite in Abhängigkeit der Motorstärke",
xlim = c(0, 350), ylim = c(0, 35)) + geom_smooth(method = "lm", se = FALSE,
formula = y ~ x, fullrange = TRUE)
Es fällt auf, dass der Grafikbereich immer noch einen Rand über den eingestellten Anzeigebereich hinaus beibehält. Wir werden später lernen, wie dieser entfernt werden kann. Wir sehen nun, dass der angezeigte Y-Achsenabschnitt mit dem in der Regressionsgleichung ermittelten Wert für den Intercept übereinstimmt.
Bislang haben wir das Argument se in der Funktion geom_smooth von seinem standardmäßigen Wert (TRUE) auf false gesetzt. Der Parmeter se bestimmt, ob um die eingezeichnete Regressionsgerade ein zusätzlicher Korridor gezeichnet wird, in dem sich die wahre Regressionsgerade mit 95%-iger Sicherheit befindet (Also der wahre Wert zu den vorhergesagten Werten). Wir aktivieren diesen Aspekt nun:
qplot(x = mtcars[, 4], y = mtcars[, 1], data = mtcars, xlab = "Motorstärke (PS)",
ylab = "Benzinverbrauch bzw. Reichweite (Miles/Gallon)", main = "Reichweite in Abhängigkeit der Motorstärke",
xlim = c(0, 350), ylim = c(0, 35)) + geom_smooth(method = "lm", se = TRUE,
formula = y ~ x, fullrange = TRUE)
Bei weiterer Betrachtung der Grafik entsteht der Eindruck, dass die dargestellte Punktewolke vielleicht besser durch eine quadratische als eine nichtquadratische Funktion beschrieben werden kann. Die Punkte scheinen also eher eine Art kurvenförmigen von oben links nach unten rechts zu haben.
Bei Regressionsanalysen wird vorausgesetzt, dass die entstehenden Residuen um den Erwartungswert 0 herum normalverteilt sind. Wenn eine lineare Regression auf einen eigentlich quadratischen Zusammenhang gelegt wird, wird diese Normalverteilungsannahme für die Residuen verletzt. Wir können die Verteilung der Residuuen für unsere Regresssionsanalyse grafisch überprüfen. Dazu erstellen wir ein Streudiagramm, in dem die standardisierten (z-transformierten) Residuen gegen die Vorhersagewerte abgetragen werden.
Zusätzlich benutzen wir den Befehl geom_line, um eine Gerade bei 0 zu erstellen. Die Residuen sollten unsystematisch um diese Gerade herum streuen. Wir färben die Linie mit einem zusätzlichen Argument rot ein:
reg.res = rstandard(reg)
qplot(x = mtcars[, 4], y = reg.res, data = mtcars, xlab = "Motorstärke (PS)",
ylab = "Standardisierte Residuen", main = "Verteilung der Residuen") + geom_line(y = 0,
colour = "red")
Es zeigt sich, dass die Residuen nicht unsystematisch um die Gerade herum streuen. Stattdessen scheinen die Residuen in den Randbereichen der Grafik eher oberhalb der roten Linie zu liegen und in der Mitte eher unterhalb. Eine derartige Verteilung von Residuen (sie ist u-förmig) deutet darauf hin, dass der Zusammenhang zwischen zwei Variablen quadratisch sein könnte. Wir testen dies, in dem wir unsere zuvor berechnete Regression erneut mit einem zusätzlichen quadratischen Term durchführen. Anschließend vergleichen wir die Güte beider Regressionsmodelle, um festzustellen, ob es hier signifikante Unterschiede gibt:
reg2 <- lm(formula = mtcars[, 1] ~ mtcars[, 4] + I(mtcars[, 4]^2), data = mtcars)
summary(reg2)
##
## Call:
## lm(formula = mtcars[, 1] ~ mtcars[, 4] + I(mtcars[, 4]^2), data = mtcars)
##
## Residuals:
## Min 1Q Median 3Q Max
## -4.551 -1.603 -0.698 1.551 8.721
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 4.04e+01 2.74e+00 14.74 5.2e-15 ***
## mtcars[, 4] -2.13e-01 3.49e-02 -6.11 1.2e-06 ***
## I(mtcars[, 4]^2) 4.21e-04 9.84e-05 4.27 0.00019 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 3.08 on 29 degrees of freedom
## Multiple R-squared: 0.756, Adjusted R-squared: 0.739
## F-statistic: 45 on 2 and 29 DF, p-value: 1.3e-09
anova(reg, reg2)
## Analysis of Variance Table
##
## Model 1: mtcars[, 1] ~ mtcars[, 4]
## Model 2: mtcars[, 1] ~ mtcars[, 4] + I(mtcars[, 4]^2)
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 30 448
## 2 29 275 1 173 18.3 0.00019 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Tatsächlich bewahrheitet sich die Vermutung, dass ein quadratisches Regressionsmodell den Zusammenhang zwischen unseren beiden Variablen besser erklären kann. Der hier verwendete anova Befehl vergleicht die Anteile der unaufgeklärten Varianz beider Modelle (Residual Sum of Squares, RSS) miteinander, wobei eine kleinere RSS für eine bessere Modellpassung steht. Da die Anova signifikant wird ist klar, dass das quadratische Regressionsmodell besser zu den empirischen Daten passt.
Wir können uns diesen quadratischen Zusammenhang ebenfalls grafisch veranschaulichen. Hierzu erweitern wir unsere ursprüngliche Grafik, die nur die nichtquadratische Regressionsgerade enthält, um eine zusätzliche Regressionsgerade (rot eingefärbt) mit verändertem formula Argument:
qplot(x = mtcars[, 4], y = mtcars[, 1], data = mtcars, xlab = "Motorstärke (PS)",
ylab = "Benzinverbrauch bzw. Reichweite (Miles/Gallon)", main = "Reichweite in Abhängigkeit der Motorstärke",
xlim = c(0, 350), ylim = c(0, 35)) + geom_smooth(method = "lm", se = FALSE,
formula = y ~ x + I(x^2), fullrange = TRUE, colour = "red") + geom_smooth(method = "lm",
se = FALSE, formula = y ~ x, fullrange = TRUE)
Mit einer weiteren Grafik lassen wir uns zusätzlich die Verteilung der Residuen des zweiten Regressionsmodells anzeigen. Der U-förmige Zusammenhang ist nun nicht mehr zu erkennen (allerdings gibt es auch bei diesem Regressionsmodell einige Ausreißer in den beobachteten Werten):
reg.res2 = rstandard(reg2)
qplot(x = mtcars[, 4], y = reg.res2, data = mtcars, xlab = "Motorstärke (PS)",
ylab = "Standardisierte Residuen", main = "Verteilung der Residuen") + geom_line(y = 0,
colour = "red")
Wir sehen, welche zentrale Rolle Streudiagramme bei der Untersuchung von Zusammenhängen zwischen Variablen spielen. Die grafische Analyse liefert uns dabei wichtige Ideen und Informationen, die wir anschließend durch statistische Analysen absichern können.
Bei der statistischen Datenauswertung ist es oft sinnvoll Häufigkeiten oder Mittelwerte von Variablen in Form von Balkendiagrammen darzustellen. So lassen sich sehr einfach Vergleiche visualisieren. In einem ersten Beisiel vergleichen wir die Häufigkeiten für die Anzahl der Zylinder von Fahrzeugen in unserem Beispieldatensatz.
Wir benutzen dafür wieder den Befehl qplot() und übergeben die Zylinderzahl als Faktor für die X-Achse. Die Umwandlung in einen Faktor ist wichtig, da ggplot2 die eigentlich als numerisch gespeicherte Variable ansonsten falsch darstellen würde (nämlich auf einem Zahlenstrahl, der ebenfalls 5 und 7 enthalten würde, nur dass dort dann die Häufigkeit 0 ist). Ansonsten übergeben wir den zu verwendenden Datensatz und einige Labels, wie auch schon im vorherigen Beispiel.
Wir geben im Unterschied nun aber keine Variable für die Y-Achse an. Dadurch werden die Häufigkeiten der einzelnen Faktorstufen (unserer X-Achse) automatisch in Balkenform dargestellt:
qplot(x = factor(mtcars[, 2]), data = mtcars, xlab = "Anzahl Zylinder", ylab = "Häufigkeit",
main = "Vergleich der Zylinderzahl")
Wenn wir statt absoluten Häufigkeiten Mittelwerte vergleichen wollen, müssen wir diese zunächst berechnen und an unsere qplot() Funktion übergeben. Dabei hilft uns die Funktion tapply(), mit der wir unsere Daten nach einer Kategorialen Variable aufteilen und dann für alle Teildatensätze eine definierte Funktion laufen lassen können. Für unser Beispiel nehmen wir die Motorleistung (mtcars[,4]) und lassen deren Mittelwerte (mean) in Abhängigkeit von der Zylinderzahl eines Fahrzeugs (mtcars[,2]) berechnen.
means = tapply(mtcars[, 4], mtcars[, 2], mean) # Mittelwerte der Motorleistung nach Zylinderzahl
Nun plotten wir die errechnete Motorleistung gegen die Faktorstufen unserer vorher genutzten faktorisierten Variable für die X-Achse (die Zylinderzahl mtcars[,2]). Hierbei ist zu beachten, dass wir nun die Funktionen levels() (Gibt uns die Bezeichnung der Faktorstufen) und factor() ineinander verschachteln. Damit wird genau ausgedrückt, dass wir die numerische Variable mtcars[,2] zunächst faktorisieren und uns dann die Faktorstufen ausgeben lassen, gegen die unsere errechneten Mittelwerte geplottet werden sollen:
qplot(x = levels(factor(mtcars[, 2])), y = means, geom = "bar", stat = "identity",
xlab = "Anzahl Zylinder", ylab = "Mittlere Motorleistung (PS)", main = "Vergleich der Motorleistung nach Zylinderzahl")
Mit Hilfe des fill Parameters können wir unsere Grafik nun auch einfärben. Dabei sagen wir ggplot2, dass wir unterschiedliche Farben je nach Zylinderzahl angezeigt bekommen wollen:
qplot(x = levels(factor(mtcars[, 2])), y = means, geom = "bar", stat = "identity",
fill = levels(factor(mtcars[, 2])), xlab = "Anzahl Zylinder", ylab = "Mittlere Motorleistung (PS)",
main = "Vergleich der Motorleistung nach Zylinderzahl")
ggplot2 ermöglicht uns eine große Menge zusätzlicher Konfigurationsmöglichkeiten und die Darstellung wichtiger Aspekte wie Fehlerbalken zu unseren Mittelwerten. Allerdings schränkt der qplot() Befehl diese Möglichkeiten sehr stark ein, um so ein möglichst unkompliziertes und schnelles Erstellen von Grafiken zu erlauben. Um die volle Bandbreite von ggplot2 ausnutzen zu können, müssen wir für komplexere Diagramme die Funktion ggplot() verwenden, die qplot() in manchen Aspekten ähnelt, aber insgesamt deutlich anders funktioniert.
Wir erstellen zunächst das ungefärbte Balkendiagramm zur Mittleren Motorleistung in Abhängigkeit der Zylinderzahl mit dem ggplot() Befehl neu. Ein grundsätzlicher Unterschied zwischen ggpplot() und qplot() besteht allerdings darin, dass ggplot alle für die Grafik relevanten Werte in einem einzelnen Datenframe erwartet und ander als qplot() keine Daten aus anderen Quellen akzeptiert. Daher müssen wir zunächst die benötigten Variablen (Anzahl der Zylinder aus mtcars und die dazu berechneten Mittelwerte aus means) in einem gemeinsamen Datenframe speichern.
Auf Basis dieses neuen Datenframes lässt sich dann ein Plot mit Hilfe von ggplot() erzeugen:
ggframe <- data.frame(means = means, cyl = levels(factor(mtcars[, 2])))
ggplot(ggframe, aes(x = factor(cyl), y = means)) + geom_bar(stat = "identity")
Entscheidende Unterschiede im Funktionsaufrauf zwischen qplot() und ggplot() bestehen darin, dass wir nun zuerst das Datenframe angeben müssen, auf dessen Basis die Grafik erstellt werden soll. Dann folgt die Zuweisung der X- und Y-Achsen innerhalb des Befehls aes(). Dadurch werden die Daten grundsätzlich für die Erstellung der Grafik eingeordnet, aber es wird noch nichts geplottet.
Die ggplot() Funktion arbeitet mit verschiedenen Ebenen (engl. layers), die man nun übereinander plotten kann. Jede Ebene wird durch einen eigenen Funktionsaufruf dargestellt, der über den + Operator mit der ggplot() Funktion verknüpft wird. Bei der qplot() Funktion haben wir dieses Prinzip schon für geom_smooth() und geom_line() kennen gelernt. Neu an ggplot() ist dagegen, dass ohne die Angabe mindestens eines Layers überhaupt keine Grafik erstellt wird, während qplot() bereits ein Layer integriert hatte.
Wir wollen uns einfach Balken für die mittlere Motorenleistung in Abhängigkeit der Zlyinderzahl anzeigen lassen. Die entsprechenden Daten haben wir ggplot() übergeben. Als Layer fügen wir nun ein geom_bar() Element hinzu. Damit hier nicht Häufigkeiten sondern die Mittelwerte geplottet werden benutzen wir innerhalb von geom_bar() noch den Parameter stat und setzen dieses auf 'identity'. Dadurch wird anstelle der Anzahl von Werten im Datenframe die genauen Werte in der Spalte für die Y-Achse (bei uns means, also die gewünschten Mittelwerte) angezeigt.
Wir können auch bei der ggplot() Funktion Titel und Beschriftungen nach unseren Wünschen anpassen. Hierzu können wir ein zusätzliches Layer definieren, welches die angepasste Beschriftungen enthält und die Standardbeschriftung überschreibt. Dieses Layer basiert auf der Funktion labs():
ggplot(ggframe, aes(x = factor(cyl), y = means)) +
geom_bar(stat = "identity") +
labs(title = "Motorleistung in Abhängigkeit der Zylinderzahl", x = "Anzahl Zylinder",
y = "Mittlere Motorleistung")
Die einzelnen Layer von ggplot() ermöglichen uns im Vergleich zu qplot() deutlich mehr Konfigurationsmöglichkeiten, da sie viele zusätzliche Parameter unterstützen. Wir können beispielsweise nun die Breite der Balken mit Hilfe des width Parameters einstellen:
ggplot(ggframe, aes(x = factor(cyl), y = means)) +
geom_bar(stat = "identity", width = 0.5) +
labs(title = "Motorleistung in Abhängigkeit der Zylinderzahl", x = "Anzahl Zylinder",
y = "Mittlere Motorleistung")
Auch die mit qplot() realisierte Einfärbung der Balken lässt sich ohne weiteres durch den fill Parameter innerhalb einer aes() Funktion realisieren:
ggplot(ggframe, aes(x = factor(cyl), y = means)) +
geom_bar(stat = "identity", width = 0.5, aes(fill = factor(cyl))) +
labs(title = "Motorleistung in Abhängigkeit der Zylinderzahl", x = "Anzahl Zylinder",
y = "Mittlere Motorleistung (PS)")
Die aes() Funktion (aes steht für aesthetics) steuert verschiedene Layoutmerkmale und kann in jedem Layer und in ggplot() selbst eingesetzt werden, wobei sie innerhalb unterschiedlicher Funktionen verschiedene Paramater unterstützt. Wir setzen aes() immer in ggplot() ein, um Die verschiedenen Achsen und Gruppen unserer Grafik zu definieren.
Da wird Grafiken, die wir mit der ggplot() Funktion erstellt haben, um beliebige Layer erweitern können, lassen sich jetzt zusätzliche Aspekte darstellen, die unserem Balkendiagramm mehr Aussagekraft verleihen. Ein Beispiel hierfür sind Fehlerbalken, die uns helfen zu erkennen, ob Mittelwertsunterschiede überzufällig sind oder nicht.
Bevor wir Fehlerbalken in unsere Grafik einbinden können müssen wir die Standardabweichung unserer Mittelwerte bestimmen und ebenfalls in unser Datenframe einbinden. Ansonsten könnten wir diese Informationen nicht innerhalb unseres Plots nutzen. An diesem Punkt wird klar, dass wir immer, wenn wir Mittelwerte und Zusatzinformationen in ggplot als Grafiken darstellen wollen, zunächst ein Datenframe erstellen müssen, dass alle notwendigen Informationen bereits enthält, weil ggplot diese nicht für uns berechnet. Um diesen Prozess zu erleichtern gibt es bereits vorgeschriebene Funktionen, die die für Grafiken benötigten Informationen aus einem Datensatz herauslesen und in ein geeignetes Datenframe einfügen.
Wir werden ab jetzt zur Aufbereitung unserer Datensätze für die grafische Darstellung die Funktion summarySE() verwenden. Diese ist allerdings nicht in R und auch in keinem normalen Zusatzpaket enthalten. Stattdessen müssen wir diese Funktion aus einer externen Quelle einlesen oder direkt in unser Skript kopieren. Der Einfachheit halber definieren wir die Funktion hier direkt in unserem Skript:
## Summarizes data. Gives count, mean, standard deviation, standard error of
## the mean, and confidence interval (default 95%). data: a data frame.
## measurevar: the name of a column that contains the variable to be
## summariezed groupvars: a vector containing names of columns that contain
## grouping variables na.rm: a boolean that indicates whether to ignore NA's
## conf.interval: the percent range of the confidence interval (default is
## 95%)
summarySE <- function(data = NULL, measurevar, groupvars = NULL, na.rm = FALSE,
conf.interval = 0.95, .drop = TRUE) {
require(plyr)
# New version of length which can handle NA's: if na.rm==T, don't count them
length2 <- function(x, na.rm = FALSE) {
if (na.rm)
sum(!is.na(x)) else length(x)
}
# This does the summary. For each group's data frame, return a vector with
# N, mean, and sd
datac <- ddply(data, groupvars, .drop = .drop, .fun = function(xx, col) {
c(N = length2(xx[[col]], na.rm = na.rm), mean = mean(xx[[col]], na.rm = na.rm),
sd = sd(xx[[col]], na.rm = na.rm))
}, measurevar)
# Rename the 'mean' column
datac <- rename(datac, c(mean = measurevar))
datac$se <- datac$sd/sqrt(datac$N) # Calculate standard error of the mean
# Confidence interval multiplier for standard error Calculate t-statistic
# for confidence interval: e.g., if conf.interval is .95, use .975
# (above/below), and use df=N-1
ciMult <- qt(conf.interval/2 + 0.5, datac$N - 1)
datac$ci <- datac$se * ciMult
return(datac)
}
Wir können die Funktion summarySE() nun verwenden, um ein Datenframe zu erzeugen, dass die Mittelwerte der Motorleistung in Abhängigkeit der Zylinderzahl enthält und dazu noch die Standardabweichung und den Standardfehler des Mittelwerts. Dazu geben wir den auszuwertenden Datensatz im Parameter data an. Die auf der Y-Achse anzuzeigende Variable muss beim Parameter measurevar angegeben werden. Zuletzt werden alle relevanten Gruppierungsvariablen (bei uns nur die Anzahl der Zylinder) in einer Liste beim Parameter groupvars übergeben:
ggframe <- summarySE(data = mtcars, measurevar = 4, groupvars = c(2))
## Loading required package: plyr
ggframe
## cyl N 4 sd se ci
## 1 4 11 82.64 20.93 6.312 14.06
## 2 6 7 122.29 24.26 9.170 22.44
## 3 8 14 209.21 50.98 13.624 29.43
Wir erhalten ein Datenframe, welches nun die geüwnschten Mittelwerte, aber auch alle benötigten Informationen zur Darstellung von Konfidenzintervallen enthält. Dieses können wir nun in unserer ursprünglichen ggplot() Funktion einsetzen:
ggplot(ggframe, aes(x = factor(cyl), y = ggframe[, 3])) +
geom_bar(stat = "identity", width = 0.5, aes(fill = factor(cyl))) +
labs(title = "Motorleistung in Abhängigkeit der Zylinderzahl", x = "Anzahl Zylinder",
y = "Mittlere Motorleistung (PS)") +
geom_errorbar(aes(ymin = ggframe[, 3] - ci, ymax = ggframe[, 3] + ci), width = 0.3,
size = 0.5)