Exploratorische Datenreduktion

Das Ziel der PCA (Hauptkomponentenanalyse) und der EFA (Exploratorische Faktorenanalyse) ist es, Daten zu reduzieren, d.h. die Interkorrelationen von Variablen durch wenige, möglichst voneinander unabhängige “Faktoren” bzw. “Komponenten” zu repräsentieren. Das ist besonders nützlich, wenn wir Daten mit vielen Variablen haben. Beide Verfahren können aufzeigen, welcher Anteil der Gesamtvarianz der Daten erklärt werden kann, wenn die Daten auf eine gewisse Anzahl Komponenten/Faktoren reduziert werden. Typischerweise können so Gruppen von Variablen, die stark miteinander interkorrelieren, zu zugrundeliegenden Dimensionen zusammengefasst werden. Für die Unterschiede zwischen den beiden Verfahren siehe die Vorlesungsunterlagen.

EFA und PCA sind beides explorative Verfahren. Bei beiden wird in der Regel keine a-priori Annahme getroffen, wie viele Dimensionen den Daten zu Grunde liegen.

Die Aufgabe solcher Verfahren ist es zunächst, herauszufinden, wieviele Faktoren extrahiert werden sollen. Wenn auf zu wenige Faktoren reduziert wird, gehen möglicherweise wertvolle Informationen verloren. Extrahiert man zu viele Faktoren, läuft man Gefahr, die Daten zu overfitten und zufällig entstandene Kovarianzen auf einen nicht vorhandenen oder unwichtigen Faktor zurückzuführen.

Die State-of-the-Art Methode, um die Anzahl zu extrahierender Faktoren zu determinieren, ist die Parallelanalyse. Dabei wird ein Datenframe mit der selben Anzahl von Variablen und derselben Stichprobengrösse simuliert, d.h. es wird eine Stichprobe aus einer Population gezogen, in der alle Interkorrelationen der Variablen = 0 sind. Auf diese Daten wird dann eine PCA/EFA angewendet und geschaut, welche Eigenwerte die zufälligen Faktoren aufweisen. Wenn die Eigenwerte der extrahierten Faktoren in unserem Datensatz grösser sind als die der entsprechenden zufälligen Faktoren, sollten sie extrahiert werden, da sie dann Varianz repräsentieren, die über das Zufallsniveau hinaus geht. Das macht man nicht nur einmal, sondern normalerweise mindestens 1000 Mal und man betrachtet dann den Mittelwert oder den Median der Verteilung der entsprechenden Eigenwerte. Manchmal - wie per default in der Funktion psych::fa.parallel(), die wir im Folgenden verwenden werden - wird auch das 95 %-Quantil benutzt, dann im Sinne eines Signifikanztests für die “Überzufälligkeit” eines beobachteten Eigenwerts.

Neben der Paralellanalyse, die wichtige empirische Hinweise zur Anzahl der zu extrahierenden Faktoren gibt, gibt es weitere Kriterien wie eine weitergehende Interpretation des empirischen Verlaufs der Eigenwerte (“Scree-Plot”) und die inhaltliche Interpretierbarkeit der Lösung (nach einer Rotation).

Sobald die Anzahl der zu extrahierenden Faktoren festgelegt ist, können die Faktoren so rotiert werden, dass möglichst eine Einfachstruktur erzielt wird. Dies ist dann erreicht, wenn es keine substantiellen Querladungen mehr gibt, jedes Item soll also nur auf einen Faktor laden und die Ladungen der Items auf einem Faktor sollten möglichst hoch und homogen sein.

Daten

Packages laden, Daten einlesen und aufbereiten:

pacman::p_load(tidyverse, haven, EFAutilities)
# Daten einlesen
data <- read_sav("https://github.com/methodenlehre/data/blob/master/beispieldaten.sav?raw=true")

# Datenframe mit nur den Items zur Lebenszufriedenheit erstellen
ls <- data %>%
  select(num_range("leben", 1:10)) %>%
  drop_na()

Die Daten der Lebenszufriedenheit bestehen aus 10 Items, welche sich auf verschiedene Aspekte/Bereiche der Lebenszufriedenheit beziehen. Die Jugendlichen wurden gefragt:

“Wie zufrieden bist Du…

Variablennamen und zugehörige Fragen
Fragen
leben1 mit deinen Schulnoten?
leben2 mit deinem Aussehen und deiner Erscheinung?
leben3 mit der Beziehung zu deinen Lehrern?
leben4 mit allem, was mit der Schule zu tun hat?
leben5 mit allem, was mit deiner Beziehung zu anderen Menschen zu tun hat?
leben6 mit deiner Person?
leben7 mit der Beziehung zu deinen Freunden?
leben8 mit der Beziehung zu deinen Eltern?
leben9 mit dem Zusammenleben mit den anderen Familienmitgliedern?
leben10 mit dem Lebensstandard und dem Ansehen deiner Familie?

Geantwortet wurde auf einer 7-stufigen Skala von 1 = “überhaupt nicht zufrieden” bis 7 = “sehr zufrieden”.

Die Fragen zur Lebenszufriedenheit können in vier Aspekte/Bereiche gegliedert werden:

Familie Item: 8, 9, 10

Schule Item: 1, 3, 4

Selbst Item: 2, 6

Freunde Item: 7, 5

Entsprechend ändern wir jetzt die Namen der Variablen, damit die Zuordnung etwas klarer wird. Um die Reihenfolge der Variablen mit ihrer inhaltlichen Ausrichtung in Übereinstimmung zu bringen, ändern wir die Reihenfolge noch mit select().

ls <- ls %>%
  rename(
    leben8_familie = leben8,
    leben9_familie = leben9,
    leben10_familie = leben10,
    leben1_schule = leben1,
    leben3_schule = leben3,
    leben4_schule = leben4,
    leben2_selbst = leben2,
    leben6_selbst = leben6,
    leben5_freunde = leben5,
    leben7_freunde = leben7
  ) %>%
  select(
    leben1_schule, leben3_schule, leben4_schule, leben2_selbst,
    leben6_selbst, leben5_freunde, leben7_freunde, leben8_familie,
    leben9_familie, leben10_familie
  )
summary(ls)
 leben1_schule   leben3_schule   leben4_schule   leben2_selbst  
 Min.   :1.000   Min.   :1.000   Min.   :1.000   Min.   :1.000  
 1st Qu.:4.000   1st Qu.:4.000   1st Qu.:4.000   1st Qu.:5.000  
 Median :5.000   Median :5.000   Median :5.000   Median :5.000  
 Mean   :4.754   Mean   :4.797   Mean   :4.435   Mean   :5.214  
 3rd Qu.:6.000   3rd Qu.:6.000   3rd Qu.:5.000   3rd Qu.:6.000  
 Max.   :7.000   Max.   :7.000   Max.   :7.000   Max.   :7.000  
 leben6_selbst   leben5_freunde  leben7_freunde  leben8_familie 
 Min.   :1.000   Min.   :1.000   Min.   :1.000   Min.   :1.000  
 1st Qu.:5.000   1st Qu.:5.000   1st Qu.:6.000   1st Qu.:5.000  
 Median :6.000   Median :6.000   Median :6.000   Median :6.000  
 Mean   :5.678   Mean   :5.594   Mean   :6.217   Mean   :5.833  
 3rd Qu.:6.000   3rd Qu.:6.000   3rd Qu.:7.000   3rd Qu.:7.000  
 Max.   :7.000   Max.   :7.000   Max.   :7.000   Max.   :7.000  
 leben9_familie  leben10_familie
 Min.   :1.000   Min.   :1.000  
 1st Qu.:5.000   1st Qu.:5.000  
 Median :6.000   Median :6.000  
 Mean   :5.627   Mean   :5.808  
 3rd Qu.:6.000   3rd Qu.:7.000  
 Max.   :7.000   Max.   :7.000  

Packages

Für EFA und PCA verwenden wir hier das Package psych.

Mit der Funktion principal() können wir PCAs berechnen. Wenn wir die Faktoren nicht rotieren, heissen die Hauptkomponenten im Output PC# (principal component #), zum Beispiel PC1. Rotieren wir die Komponenten mit einer orthogonalen Rotationsmethode, werden sie als RC# (rotated component #) beschrieben, zum Beispiel RC1. Rotieren wir sie mit einer obliquen Rotationsmethode, werden sie als TC# (transformed component #) beschrieben, zum Beispiel TC1.

Für die EFA verwenden wir die Funktion fa(). Für die von uns betrachtete Maximum-Likelihood-EFA benötigen wir noch das Argument fm = "ml".

Im Package psych nehmen die Funktionen für PCA und EFA direkt das Datenframe als Input. Zusätzlich müssen die Anzahl zu extrahierender Komponenten/Faktoren definiert werden, und ob bzw. wie sie rotiert werden sollen.

Für die ML-EFA: Um Konfidenzintervalle (CI) und Standardfehler (SE) zu schätzen, benötigen wir zusätzlich das Package EFAutilities.

Die Funktion fa.parallel() führt eine Parallelanalyse sowohl für die PCA als auch für die EFA durch.

Beurteilung der Angemessenheit einer PCA/EFA für die Daten

Bevor eine PCA/EFA durchgeführt wird, muss zunächst sichergestellt sein, dass sich die Daten aufgrund ihrer Korrelationsstruktur auch für eine Dimensionsreduktion im Sinne der PCA/EFA eignen. Wir betrachten in einem ersten Schritt die Korrelationsmatrix und verschaffen uns so einen Überblick über die Zusammenhänge in den Daten. Danach führen wir den Bartlett’s Test auf Sphärizität durch, gefolgt von der Berechnung des KMO-MSA (Kaiser-Meyer-Olkin Measure of Sampling Adequacy).

Korrelationen

Deskriptiver Überblick über die Interkorrelationsstruktur der Items: pairs.panels() aus psych gibt einen Plot aus, der Informationen zur Korrelationsmatrix visualisiert. An diesem Plot (siehe Abbildung nächste Seite) kann man sehen, dass praktisch alle Items in einem gewissen Masse miteinander korrellieren, manche (insbesondere solche aus dem selben Inhaltsbereich) aber stärker als andere. Insgesamt zeigen sich aber keine allzu starken korrelativen Zusammenhänge zwischen den Lebenszufriedenheitsvariablen.

Ausserdem können wir anhand der abgebildeten Streudiagramme eine grundlegende Korrelations- bzw. Regressionsdiagnostik vornehmen: Voraussetzung für die PCA/EFA sind lineare Zusammenhänge (da lineare Korrelationen als Input verwendet werden) und dass keine Outlier vorliegen. Für die Maximum-Likelihood EFA ist ausserdem multivariate Normalverteilung Voraussetzung. Da einige Outlier zu erkennen sind, die auch die Linearität der Zusammenhänge massgeblich verzerren (siehe rote Linien z.B. beileben5_freunde \(\leftrightarrow\) leben9_familie) ist es als Vorsichtsmassnahme ratsam, univariate Outlier, die mehr als 3 Standardabweichungen vom Mittelwert der jeweiligen Variablen entfernt sind, aus den Daten zu entfernen.

Outlier-Entfernung:

# Definition einer Funktion `keep`, die nur Datenpunkte auswählt, die zwischen
# +/- 3 Standardabweichungen einer Variablen liegen
keep <- function(x) {
  mx <- mean(x) # Wir speichern den Mittelwert der Variable
  sd3 <- 3 * sd(x) # Hier speichern wir die Standardabweichung * 3
  between(x, left = mx - sd3, right = mx + sd3)
}

# Wir nutzen die Funktion filter(). Wir behalten alle Rows (Personen), die keinen Wert haben,
# der stärker vom Variablen-Mittelwert abweicht als 3 sd's.
ls_clean <- ls %>%
  filter(rowMeans(sapply(ls, keep)) == 1)

Durch die Entfernung der Outlier hat sich der Datensatz von \(n=276\) auf \(n=255\) reduziert, insgesamt wurden also 21 Personen oder 7,6 % der Daten entfernt. Ohne Outlier zeigen sich insgesamt etwas schwächere korrelative Zusammenhänge und auch kaum mehr offensichtliche Verzerrungen der linearen Zusammenhänge durch Outlier bzw. einflussreiche Datenpunkte (siehe Plots erstellt mit pairs.panels())

Jetzt können wir das bereinigte Datenfile abspeichern, damit wir in den nächsten Kapiteln darauf zurückgreifen können:

library(readr)
write_csv(
  x = ls_clean,
  file = "data/ls_clean.csv"
)

Wir haben die Daten ausserdem auf GitHub gespeichert, dadurch können Sie auch die bereinigten Daten für die kommenden Kapitel direkt herunterladen.

pairs.panels(ls, density = FALSE, jiggle = TRUE, ci = TRUE, stars = TRUE)

pairs.panels(ls_clean, density = FALSE, jiggle = TRUE, ci = TRUE, stars = TRUE)

Mit dieser Methode haben wir nur univariate Ausreisser detektiert. Es ist jedoch möglich, dass multivariate Ausreisser weiterhin nicht entdeckt werden. Das könnte zum Beispiel ein Datenpunkt sein, der jeweils innerhalb zwei oder drei Standardabweichungen vom Mittelwert liegt, dann aber bivariat angeschaut weit weg liegt von anderen Datenpunkten. Eine Methode, solche Datenpunkte zu detektieren, ist der Mahalanobis-Abstand. In R können wir dafür die Funktion mahalanobis() aus dem standardmässig schon installierten Package stats verwenden.

Bartlett’s Test auf Sphärizität

Der Bartlett’s Test auf Sphärizität bewertet, ob die Variablen überhaupt miteinander korrelieren oder nicht, indem er die beobachtete Korrelationsmatrix gegen eine “Identitätsmatrix” (eine Matrix mit Einsen entlang der Hauptdiagonalen und Nullen überall sonst) testet. Wenn dieser Test statistisch nicht signifikant ist, sollten faktoranalytische Verfahren grundsätzlich nicht verwendet werden.

# Zuerst brauchen wir eine Korrelationsmatrix
ls_clean.cor <- cor(ls_clean)
# Bartlett's Test
cortest.bartlett(ls_clean.cor, n = length(ls$leben1_schule))
$chisq
[1] 619.2413

$p.value
[1] 5.499974e-102

$df
[1] 45

Der Bartlett Test ist signifikant. Es gibt also insgesamt signifikante Interkorrelationen der Items, eine Grundvoraussetzung für die Faktorenanalyse.

Visualisiert bedeutet das, dass der Bartlett Test folgende Matrizen verglichen und Unterschiede festgestellt hat.

KMO-MSA (Kaiser-Meyer-Olkin Measure of Sampling Adequacy)

Das KMO-MSA stellt eine Masszahl für die Bewertung der Eignung der beobachteten Variablen für eine Faktorenanalyse dar. Es prüft unter anderem, ob die partiellen Korrelationen der Variablen (bivariate Korrelationen partialisiert für jeweils alle anderen Variablen) nahe genug an Null liegen, um darauf hinzudeuten, dass den Variablen mindestens ein latenter Faktor zugrunde liegt. Ein höheres KMO-MSA weist auf eine bessere Eignung hin. Das KMO-MSA ist ganz einfach mit der KMO-Funktion des psych-Packages zu finden.

# Die KMO-Funktion nimmt als Input entweder das Datenframe oder
# eine Korrelationsmatrix. Einfachheitshalber verwenden wir hier
# das Datenframe als input.
KMO(ls_clean)
Kaiser-Meyer-Olkin factor adequacy
Call: KMO(r = ls_clean)
Overall MSA =  0.68
MSA for each item = 
  leben1_schule   leben3_schule   leben4_schule   leben2_selbst   leben6_selbst 
           0.73            0.60            0.62            0.66            0.68 
 leben5_freunde  leben7_freunde  leben8_familie  leben9_familie leben10_familie 
           0.74            0.70            0.67            0.64            0.79 

Im Output findet man den Overall MSA: Einen Kennwert der anzeigt, wie gut sich die Daten (d.h. alle Variablen zusammen) insgesamt für eine Faktorenanalyse eignen. Zusätzlich wird für jedes Item ein MSA ausgegeben.

Nach Kaiser (1975) sind Kennwerte unter 0,5 unakzeptabel (unacceptable), ab 0,5 miserabel (miserable), ab 0,6 mittelmässig (mediocre), ab 0,7 mässig (middling), ab 0,8 gut (meritorious) und ab 0,9 fantastisch (marvelous).

Unsere Daten eignen sich also mit einem Gesamt-KMO-MSA von 0,68 mittelmässig bis mässig für eine Hauptkomponentenanalyse/Faktorenanalyse. Dies trifft auch für alle einzelnen Variablen zu (MSAs zwischen 0,60 und 0,79).