Bei der Analyse größerer Datensätze untersuchen wir die Variablen oft auch auf Korrelationen. Dies kann einerseits wichtige deskriptive Informationen liefern und so zur Hypothesenbildung 1 beitragen oder auch als Voraussetzungsprüfung im Rahmen einer multiplen linearen Regression oder ANOVA dienen.2

Prinzip hinter Korrelationsmatrizen

Häufig werden zur Untersuchung der Zusammenhänge zwischen mehr als zwei Variablen sogenannte Korrelationsmatrizen verwendet. In einer Korrelationsmatrix sind alle Variablen miteinander korreliert; dargestellt werden die Korrelationskoeffizienten:

$$ r_{x_i} = \begin{bmatrix} r_{x_1, x_1} & r_{x_1, x_2} & r_{x_1, x_3} & r_{x_1, x_4} \\ r_{x_2, x_1} & r_{x_2, x_2} & r_{x_2, x_3} & r_{x_2, x_4} \\ r_{x_3, x_1} & r_{x_3, x_2} & r_{x_3, x_4} & r_{x_3, x_4} \\ r_{x_4, x_1} & r_{x_4, x_2} & r_{x_4, x_3} & r_{x_4, x_4} \end{bmatrix} $$

In dieser Korrelationsmatrix repräsentieren jede Zeile und jede Spalte eine Variable. In der Hauptdiagonalen wird jeweils die Variable mit sich selbst korreliert ($\rightarrow r = 1$). Da die Matrix symmetrisch ist, genügt die Darstellung in Form einer unteren Dreiecksmatrix – also alle Elemente inklusive und unter der Hauptdiagonale.

$$ r_{x_i} = \begin{bmatrix} 1 & \times & \times & \times \\ r_{x_2, x_1} & 1 & \times & \times \\ r_{x_3, x_1} & r_{x_3, x_2} & 1 & \times \\ r_{x_4, x_1} & r_{x_4, x_2} & r_{x_4, x_3} & 1 \end{bmatrix} $$

Korrelationen in R

In R kann eine tabellarische Korrelationsmatrix mit dem einfachen cor()-Befehl erstellt werden. Unser Datensatz enthält die Variablen MotherEdu, FatherEdu, TVs, Books und Reading; diese wollen wir miteinander korrelieren. Um eine übersichtliche Darstellung zu erhalten, ist es empfehlenswert, die Werte direkt auf zwei Nachkommastellen runden zu lassen.

round(cor(PISA2009[, c("MotherEdu", "FatherEdu", "TVs", "Books", "Reading")], use = "complete.obs"), 2)
##           MotherEdu FatherEdu   TVs Books Reading
## MotherEdu      1.00      0.46 -0.12  0.42    0.36
## FatherEdu      0.46      1.00 -0.12  0.38    0.29
## TVs           -0.12     -0.12  1.00 -0.17   -0.09
## Books          0.42      0.38 -0.17  1.00    0.41
## Reading        0.36      0.29 -0.09  0.41    1.00

Die Tabelle beinhaltet alle wichtigen Informationen, ist allerdings visuell nicht sonderlich ansprechend. Da geht mehr! Mit der Basis-Plot-Funktion erhält man eine nur wenig übersichtliche Anhäufung von Streudiagrammen. Das ist nicht das mehr, das wir meinten.

plot(PISA2009[, c("MotherEdu", "FatherEdu", "TVs", "Books", "Reading")]) 

Graphische Korrelationsmatrizen mit ggplot2

Um eine Korrelationsmatrix graphisch darzustellen, kann das Paket ggplot2 verwendet werden. Dafür muss jedoch zunächst das Datenformat angepasst werden. ggplot2 kommt nur mit Dataframes klar, die sich im Long-Format befinden. Im Long-Format sind die Variablen alle in einer Spalte gesammelt, die Werte in einer zweiten Spalte und die Kombinationen an Variablen werden zeilenweise dargestellt.

Datensatz vorbereiten

Wir speichern uns zunächst die Korrelationskoeffizienten aus der cor()-Funktion:

cor <- round(cor(PISA2009[,c("Books", "FatherEdu", "MotherEdu", "Reading", "TVs")], use = "complete.obs"), 1)

Anschließend können wir mit der melt()-Funktion aus dem Paket reshape2 die Matrix aus dem Long-Format in einen Dataframe im Wide-Format überführen. Dabei schmilzen die Spalten förmlich zusammen und ergeben einen längeren, aber schmaleren Datensatz.

cor <- melt(cor)

Der Datensatz sieht nun so aus:

##         Var1      Var2 value
## 1      Books     Books   1.0
## 2  FatherEdu     Books   0.4
## 3  MotherEdu     Books   0.4
## 4    Reading     Books   0.4
## 5        TVs     Books  -0.2
## 6      Books FatherEdu   0.4
## 7  FatherEdu FatherEdu   1.0
## 8  MotherEdu FatherEdu   0.5
## 9    Reading FatherEdu   0.3
## 10       TVs FatherEdu  -0.1
## 11     Books MotherEdu   0.4
## 12 FatherEdu MotherEdu   0.5
## 13 MotherEdu MotherEdu   1.0
## 14   Reading MotherEdu   0.4
## 15       TVs MotherEdu  -0.1
## 16     Books   Reading   0.4
## 17 FatherEdu   Reading   0.3
## 18 MotherEdu   Reading   0.4
## 19   Reading   Reading   1.0
## 20       TVs   Reading  -0.1
## 21     Books       TVs  -0.2
## 22 FatherEdu       TVs  -0.1
## 23 MotherEdu       TVs  -0.1
## 24   Reading       TVs  -0.1
## 25       TVs       TVs   1.0

Nun können wir mit ggplot2 die Korrelationsmatrix graphisch darstellen. Als geom verwenden wir geom_tile() – die Werte werden durch farbige Rechtecke repräsentiert.

Plot erstellen

ggplot(data = cor, aes(x=Var1, y=Var2, fill=value)) +
  geom_tile()

Farbschema anpassen

Standardmäßig werden die Werte durch einen Gradienten von hellblau bis dunkelblau repräsentiert. Um dies zu ändern, können wir mit der Funktion scale_fill_gradient2() die Farbrepräsentation anpassen. Mit dem Argument low wählen wir aus, durch welche Farbe niedrige Werte repräsentiert werden – analog werden hohe Werte durch high repräsentiert. Da für die Interpretation von Korrelationskoeffizienten vor allem entscheidend ist, ob überhaupt eine Korrelation besteht, sollte auch eine Repräsentation für Nullkorrelationen bestehen. Auf der Skala des Korrelationskoeffizienten (limit = c(-1,1)) befindet sich die Nullkorrelation in der Mitte (midpoint = 0), weswegen hierfür das Argument mid definiert wird. Darüber hinaus können wir die Achsenbeschriftungen mit labs(x = NULL, y = NULL) entfernen und als Theme theme_minimal()3 auswählen.

ggplot(data = cor, aes(x=Var1, y=Var2, fill=value)) +
  geom_tile()  +
  scale_fill_gradient2(low = "red", high = "lightblue", mid = "white", 
                       midpoint = 0, limit = c(-1,1),
                       name="Correlation\nCoefficient") +
  labs(x = NULL, y = NULL) +
  theme_minimal()

Hinweis
Hin und wieder ist es erforderlich, einen Zeilenumbruch in einer Achsenbeschriftung, einer Plot-Überschrift oder einem Legenden-Titel vorzunehmen. Hierfür wird der Befehl \n verwendet. Leerzeichen sind keine erforderlich.

Der aktuelle Plot weist zwei Probleme auf:

  1. Die Hauptdiagonale geht von rechts oben nach links unten. Idealerweise sollte sie jedoch von links oben nach rechts unten verlaufen. Dadurch wird sichergestellt, dass die Variablennamen direkt an den tiles anliegen und der Plot gut lesbar ist.
  2. Eine Hälfte der graphische Korrelationsmatrix ist redundant.

Diese beiden Probleme können gelöst werden, indem wir den Datensatz weiter anpassen. Mit der Funktion upper.tri() werden die Elemente rechts jenseits der Hauptdiagonale ausgewählt. Damit können wir diese Werte mit NA überschreiben. Anschließend wird der Datensatz mit melt() „geschmolzen“.

Hauptdiagonale spiegeln

Um die Richtung der Hauptdiagonalen im Plot zu verändern, müssen die Variablen aus zwei Richtungen ausgelesen werden. Hierfür kann die reorder()-Funktion aus dem dplyr-Paket direkt in der aes()-Funktion von ggplot2 verwendet werden.

ggplot(data = cor, aes(reorder(Var2,  -desc(as.character(Var2))), 
                       reorder(Var1,  desc(as.character(Var1))), fill=value)) +
  geom_tile(color = "white") +
  scale_fill_gradient2(low = "red", high = "lightblue", mid = "white", 
                       midpoint = 0, limit = c(-1,1), space = "Lab", na.value = "white",
                       name="Correlation\nCoefficient") +
  labs(x = NULL, y = NULL,
       title = "Correlation Matrix") +
  geom_text(aes(label = round(value,3))) +
  theme_minimal()

Den gewonnen Weißraum können wir verwenden, um die Legende platzsparend zu positionieren:

ggplot(data = cor, aes(reorder(Var2,  -desc(as.character(Var2))), 
                       reorder(Var1,  desc(as.character(Var1))), fill=value)) +
  geom_tile(color = "white") +
  scale_fill_gradient2(low = "red", high = "lightblue", mid = "white", 
                       midpoint = 0, limit = c(-1,1), space = "Lab", na.value = "white",
                       name="Correlation\nCoefficient") +
  labs(x = NULL, y = NULL,
       title = "Correlation Matrix") +
  geom_text(aes(label = round(value,3))) +
  theme_minimal() +   
  theme(legend.key.size = unit(.8, "cm"),
        legend.position = c(0.8, 0.75))

Hinweis
Da es sich meist um Pearson-Korrelationen handelt, muss der Korrelationskoeffizient in diesem Fall nicht näher erläutert werden. Sollten allerdings andere Verfahren wie Kendalls $\tau$ oder Spearmans $\rho$ zum Einsatz kommen, sollte dies angegeben werden.

Signifikanzen darstellen

Grundsätzlich sollten uns nur solche Korrelationen interessieren, die auch statistisch signifikant sind. In R lassen sich Korrelationen mit der cor.test()-Funktion testen. Allerdings kommt diese Funktion nur mit zwei Variablen klar.

$p$-Werte bestimmen und zum Datensatz hinzufügen

Eine Alternative für mehrere Tests bietet die corr.test()-Funktion aus dem psych-Paket. Diese gibt neben der Korrelationsmatrix eine Matrix für die $p$-Werte der Korrelationen aus. Dies machen wir uns zunutze, um die Signifikanzen in den Plot zu integrieren. Dabei gehen wir weitestgehend analog zur Erstellung des Datensatzes cor vor, um die Variable p.value am Ende an den ursprünglichen cor-Datensatz anzufügen.

cor_p <- psych::corr.test(PISA2009[,c("Books", "FatherEdu", "MotherEdu", "Reading", "TVs")], 
                       use = "complete.obs", 
                       alpha = .05)$p # p-Werte speichern
cor_p[upper.tri(cor_p)] <- NA # Redundante Werte überschreiben
cor_p <- cor_p |> melt() # Matrix schmelzen
cor <- cbind(cor, cor_p$value) # p-Werte an ursprünglichen Datensatz anfügen
colnames(cor)[4] <- c("p.value") # Variablennamen anpassen

$p$-Werte mit ggplot2 abbilden

Da in ggplot2 die Funktion geom_text() nur einmal verwendet werden kann, müssen wir einen Workaround finden, um dennoch sowohl die Korrelationskoeffizienten als auch die $p$-Werte darzustellen. Ein möglicher Weg ist die paste()-Funktion, mit der sich verschiedene Elemente als character kombinieren und ausgeben lassen.

cor_plot <- ggplot(data = cor, aes(reorder(Var2,  -desc(as.character(Var2))), 
                       reorder(Var1,  desc(as.character(Var1))), fill=value)) +
              geom_tile(color = "white") +
              scale_fill_gradient2(low = "red", high = "lightblue", mid = "white", 
                                   midpoint = 0, limit = c(-1,1), space = "Lab", na.value = "white",
                                   name="Correlation\nCoefficient") +
              labs(x = NULL, y = NULL) +
              theme_minimal() +
              theme(legend.key.size = unit(.8, "cm"),
                    legend.position = c(0.8, 0.75))

cor_plot + geom_text(aes(label = paste("r =", round(value, 3), "\n", "p =", round(p.value, 4))),
                     color = "black", size = 3.5)

Leider werden nun auch alle NA für die Elemente oberhalb der Hauptdiagonale angezeigt. Dies liegt daran, dass die paste()-Funktion den Typ character ausgibt und ggplot2 somit nicht in der Lage ist, zu evaluieren, ob es sich um einen NA handelt oder nicht. Doch dieses Problem lässt sich mit einer logischen Abfrage und einem kleinen Trick lösen. Der Trick dabei ist, dass leere Anführungszeichen keinen Text darstellen.

cor_plot + geom_text(aes(label = ifelse(is.na(value), 
                                        "", 
                                        paste("r =", round(value, 3), "\n", "p =", round(p.value, 3)))), 
                     color = "black", size = 3.5)

  1. für künftige Forschungsvorhaben ↩︎

  2. Dabei wird vor allem überprüft, ob die vorhersagenden, unabhängigen Variablen zu stark untereinander korrelieren. Wenn dies der Fall ist, wird von Multikollinearität gesprochen. Diese hat zur Folge, dass die Schätzung der Korrelationsgewichte weniger stabil und die Aussagekraft des Modells verringert sind. Im besten Fall ist eine der Variablen redundant (fügt dem Modell also keine Vorhersagekraft hinzu) und kann aus dem Modell entfernt werden. ↩︎

  3. theme_minimal() hat den Vorteil, dass kein hellgrauer, leicht überstehender Hintergrund besteht. ↩︎