FA Rmd

Das Thema Faktoranalyse wird in 3 Unterthemen gesplittet, die jeweils in einer Unit besprochen werden.

  • PCA, Hauptkomponentenanalyse (Principal Component Analysis) PCA

  • EFA, Explorative Faktoranalyse (Exploratory Factor Analysis) EFA

  • CFA, Konfirmative Faktoranalyse (Confirmative Factor Analysis) CFA

Abgrenzungen und Bemerkungen

Faktoranalysen reproduzieren Korrelationsmatrizen. Ausgangspunkt müssen also nicht unbedingt Rohdaten sein, Korrelationsmatrizen reichen.

PCA und EFA sind konzeptionell verschieden aber rechnerisch vergleichbar. PCA ist ein Sonderfall der EFA für spezielle Anwendungszwecke.

PCA kann beispielsweise zur Reduktion der Anzahl von Variablen dienen, vor allem dann, wenn es Probleme mit Multikollinearität gibt (zu hohe Interkorrelationen von Prädiktoren). In diesem Anwendungsfall können die Prädiktoren in eine adäquate Anzahl von Komponenten zerlegt werden. Alle darauf folgenden Berechnungen werden dann mit den Komponentenwerten durchgeführt.

In der PCA geht man davon aus, dass alle Varianz einer Variablen ‘common Variance’ ist, also durch einen gemeinsamen Einfluss zu 100% festgelegt ist. Daher werden die Kommunalitäten auf 1 (100%) festgelegt.

Im Unterschied zur PCA, die möglichst viel erklärbare Varianz in den Komponenten erklären will, geht man in der EFA von Anfang an davon aus, dass man nur einen gewissen Teil der Varianz erklären kann. Variablen werden nur als Indikatoren von dahinter liegenden Faktoren (latent Traits) aufgefasst und diese Faktoren können gar nicht vollständig erklärt werden durch die Indikatorvariablen.

Es ergibt sich das Problem der Kommunalitätenschätzung. Da die Kommunalität der Anteil der erklärbaren Gesamtvarianz ist, der durch die Gesamtheit der Faktoren erklärt werden kann, müssen adäquate maximale Kommunalitäten geschätzt werden. Der durch die sog. gemeinsamen Faktoren nicht erklärbare Varianzanteil in den Variablen wird spezifischer Varianzanteil genannt.

Die PCA beinhaltet also kein Fehlermodell, sondern betrachtet alle Komponenten als gleichwertig. Damit wird davon ausgegangen, dass die gesamte Varianz in den Variablen durch die vollständige Hauptkomponentenlösung erklärbar ist.

CFA ist ein Sonderfall der Pfadanalyse. Sie dient hauptsächlich dazu, eine bereits gegebene Faktorstruktur zu überprüfen. Die bekannte Faktorstruktur kann aus Vorstudien stammen, oder aber theoretisch abgeleitet sein, muss aber a priori festliegen. Es wird die Hypothese getestet, ob das spezifische Faktor-Modell eine vorliegende Kovarianz- oder Korrelationsmatrix adäquat beschreiben kann (model fit). Es wird ein Chi^2 Test auf Unterschiedlichkeit berechnet und es können verschiedene Fit-Indices angefordert werden.

Anzahl der Faktoren

Den explorativen Verfahren CFA und EFA ist gemein, dass unklar ist, wieviele Faktoren überhaupt extrahiert werden sollten. Inhaltlichen Überlegungen hierzu können ein Weg sein, die Anzahl festzulegen, beispielsweise aufgrund theoretisch abgeleiteter, ganz gezielter Formulierung von zwei Gruppen von Fragen.

Bei nicht inhaltlich vorgegebener Faktorenanzahl muss die Anzahl anders festgelegt werden. Häufig wird hierzu ein Screeplot angefertigt: Die Eigenwerte werden der Höhe nach geordnet in einem Diagramm angezeigt. Es wird nach einem ‘Knick’ gesucht. Subjektives Kriterium.

Ein anderes, gängiges Kriterium ist das Kaiser-Guttman-Kriterium, häufig auch nur Kaiser-Kriterium genannt. Hierbei ist die Anzahl der Faktoren gleich derer mit einem Eigenwert über 1. Idee dahinter: Ein Eigenwert von 1 resultiert, wenn ein Faktor einen ‘durchschnittlichen’ Anteil an Varianz erklärt. Die Summe der Eigenwerte ist gleich der Anzahl der faktorisierten Variablen.

Parallelanalyse

Parallelanalyse dient als Hilfsmittel zum Festlegen der Faktorenanzahl. Die Idee ist, Zufallsdatensätze zu faktorisieren, die dieselben Charakteristika haben, wie der zu untersuchende Datensatz. Dies bezieht sich auf Vpn und Variablen. Auch hier gibt es Eigenwerte über 1. Mittlerer Eigenwertverlauf hieraus ist Vergleichsverlauf. Empirische Eigenwerte des eigenen, untersuchten Datensatzes, die über den Werten des gemittelten Zufalls-Eigenwertverlaufs liegen, können als bedeutsam betrachtet werden.

Mit der Parallelanalyse steht ein nicht-subjektives Vorgehen zur Festlegung der Faktorenzahl zur Verfügung.

In R stellt die Library psych mit dem Befehl fa.parallel() die Parallelanalyse zur Verfügung. Diese Prozedur erzeugt auch einen entsprechenden aussagefähigen Plot.

Mit dem Paramter fa=... fordert man eine Parallelanalyse für PCA fa='pc', für Hauptachsenanalyes (principal axis factor analysis) fa='fa' oder beide zugleich fa='both' an.

Parallelanalyse SAQ-Beispiel von Andy Field (2013)

SAQ: SPSS-Anxiety-Questionnaire Field (2013, p. 683)

stroop-fig

Erfundene Daten. Idee ist, mit einem Inventar, dem Spss-Anxiety-Questionnaire (SAQ) die Angst Studierender vor SPSS zu erfassen. Insgesamt 23 Statements werden auf einer 5-stufigen Lickert-Skala beantwortet.

sd = strongly disagree d = disagree n = neither agree nor disagree a = agree sa = strongly agree

Der SAQ liegt von insgesamt 2571 Personen vor. Frage: Kann die Angst im Umgang mit SPSS heruntergebrochen werden auf spezifische Subkomponenten von Angst? Welche latenten Eigenschaften tragen zur Angst vor SPSS bei?

# first 23 columns of saq.txt are the 23 items of the questionnaire. So we read only these columns
dd <- read.delim("http://md.psych.bio.uni-goettingen.de/mv/data/af/saq.txt")[1:23]
#head(dd)
# take a look at the eigenvalues
eigen(cor(dd))$values
##  [1] 7.2900471 1.7388287 1.3167515 1.2271982 0.9878779 0.8953304 0.8055604
##  [8] 0.7828199 0.7509712 0.7169577 0.6835877 0.6695016 0.6119976 0.5777377
## [15] 0.5491875 0.5231504 0.5083962 0.4559399 0.4238036 0.4077909 0.3794799
## [22] 0.3640223 0.3330618
# parallel analysis is part of library(psych)
library(psych)
# get parallel analysis for both types of fa (principal axis factor analysis, principal component analysis)
items.parallel <- fa.parallel(dd, fa="both")

## Parallel analysis suggests that the number of factors =  6  and the number of components =  4
# you may also get parallel analysis for one type only: here principal component analysis
# items.parallel <- fa.parallel(dd, fa="pc")
# you may also get parallel analysis for principal axis factor analysis only
# items.parallel <- fa.parallel(dd, fa="fa")
# the command below generates the graph
# plot(items.parallel)

Ein Plot ähnlich diesem sollte erzeugt werden:

parallel_plot_pc parallel_plot_pc.png

Bem: Eine Meldung von Fehler in values.sim$mean : $ operator is invalid for atomic vectors … ist bisher noch ungelöst. Plot erscheint trotzdem.

Mehr Beispiele sind bei den speziellen Verfahren zu finden.

source von fa.parallel()

Bartlett-Test

Ist die zu faktorisierende Korrelationsmatrix signifikant von einer Identitätsmatrix (alle Elemente sind 0) verschieden? Eine Minimalvoraussetzung für Faktorisierung.

dd <- read.delim("http://md.psych.bio.uni-goettingen.de/mv/data/virt/v_bmi_preprocessed.txt", fileEncoding = "UTF-8")
require(dplyr)
## Loading required package: dplyr
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
dd.f <- dplyr::select(dd, c(c_phys_app:c_dress, i_c_bad_way, c_figure))
require(psych)
# Ask Bartlett test whether correlation matrix is idendity matrix (all elements are 0), should be significant
# run Bartlett test on dataframe
cortest.bartlett(dd.f)
## R was not square, finding R from data
## $chisq
## [1] 148.9133
## 
## $p.value
## [1] 6.236252e-27
## 
## $df
## [1] 10
# alternativly on correlation matrix (add n), here calculated on the fly using cor()
cortest.bartlett(cor(dd.f), n=length(dd.f[,1]))
## $chisq
## [1] 148.9133
## 
## $p.value
## [1] 6.236252e-27
## 
## $df
## [1] 10

KMO Kaiser-Meyer-Olkin Measure of Sampling Adequacy bzw Kaiser-Meyer-Olkin-Kriterium

Beurteilung der Eignung der Daten zur Durchführung einer EFA. Das am häufigsten benutzte Verfahren, um die Eignung von Daten für die Faktorenanalyse zu bestimmen, ist das Kaiser-Meyer-Olkin (KMO) Maß.

vgl. Wikipedia Artikel zu KMO

vgl. Eric Klopp EFA

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

\[ KMO = \frac{\sum_{k \neq j} r^2_{jk}} {\sum_{k \neq j} r^2_{jk} + \sum_{k \neq j} p^2_{jk}} \]

\(r_{jk}\) ist die Korrelation zwischen zwei Variablen.

\(p_{jk}\) ist die partielle Korrelation zwischen zwei Variablen.

wobei \(r_{ij}\) der Korrelationskoeffizient der Variablen i und j ist und \(r_{ij.z}\) der partielle Korrelationskoeffizient nach Herauspartialisierung aller anderen Variablen ist. Stehen hinter dem Datensatz gemeinsame Faktoren und lädt jeder Faktor auf mindestens drei Indikatoren (Variablen), dann sollten die partiellen Korrelationen nahe Null sein. Man bestimmt also den gemeinsamen Varianzanteil, den alle Variablen miteinander teilen, und setzt diesen mit dem gemeinsamen Varianzanteil aller Variablen miteinander zuzüglich der Summe der quadrierten Partialkorrelationskoeffizienten, in Beziehung. Eine große Summe der Partialkorrelationskoeffizienten bedeutet, dass die Interkorrelationsmatrix wenig gemeinsame Varianz enthält und somit wird der KMO-Koeffizient klein. Um die Eignung einer Interkorrelationsmatrix beurteilen zu können, gelten folgende Anhaltspunkte (nach Kaiser und Rice, 1974):

KMO-Koeffizient Eignung der Daten
>0,90 sehr gut
0,80-0,90 gut
0,70-0,79 mittel
0,60-0,69 mäßig
0,50-0,59 schlecht
<0,50 inkompatibel mit der Berechnung

library(psych) bietet mit KMO() einen Befehl hierfür.

Kaiser-Meyer-Olkins Measure of Sampling Adequacy gibt es als Gesamtmaß MSA und für jede einzelne Variable MSAi.

# first 23 columns of saq.txt are the 23 items of the questionnaire. So we read only these columns
dd <- read.delim("http://md.psych.bio.uni-goettingen.de/mv/data/af/saq.txt")[1:23]
# KMO is part of library(psych)
library(psych)
# get the KMO coefficients
kmo <- KMO(dd)
# show it
kmo
## Kaiser-Meyer-Olkin factor adequacy
## Call: KMO(r = dd)
## Overall MSA =  0.93
## MSA for each item = 
## Question_01 Question_02 Question_03 Question_04 Question_05 Question_06 
##        0.93        0.87        0.95        0.96        0.96        0.89 
## Question_07 Question_08 Question_09 Question_10 Question_11 Question_12 
##        0.94        0.87        0.83        0.95        0.91        0.95 
## Question_13 Question_14 Question_15 Question_16 Question_17 Question_18 
##        0.95        0.97        0.94        0.93        0.93        0.95 
## Question_19 Question_20 Question_21 Question_22 Question_23 
##        0.94        0.89        0.93        0.88        0.77
# get ordered MSAi
kmo$MSAi[order(kmo$MSAi)]
## Question_23 Question_09 Question_08 Question_02 Question_22 Question_20 
##   0.7663994   0.8337295   0.8713055   0.8747754   0.8784508   0.8890514 
## Question_06 Question_11 Question_21 Question_01 Question_17 Question_16 
##   0.8913314   0.9059338   0.9293369   0.9297610   0.9306205   0.9336439 
## Question_15 Question_19 Question_07 Question_18 Question_13 Question_10 
##   0.9404402   0.9407021   0.9416800   0.9479508   0.9482270   0.9486858 
## Question_03 Question_12 Question_04 Question_05 Question_14 
##   0.9510378   0.9548324   0.9553403   0.9600892   0.9671722

Gesamt-Statistik (MSA) und Statistik für jede Variable (MSAi) wird ausgegeben. Bewertung: .5 - .7 mäßig, .7 - .8 gut, .8-.9 sehr gut, über .9 super Empfehlung: Variablen mit einem Kaiser-Meyer-Olkin Measure of Sampling Adequacy von unter 0.5 ausschließen (MSA steht für Measure of Sampling Adequacy).

Fazit: Die SAQ-Daten von Andy Field eigenen sich sehr gut für eine Faktorisierung (Overall MSA = 0.93 > 0.9). Kein MSAi ist kleiner als .75, die Mehrzahl liegt über .90. Es gibt keinen Anlass, eine der Variablen aus der Faktorisierung zu nehmen.

Reproduzierte Korrelationsmatrix und Residuen, Chi^2 Modelltest

dd <- read.delim("http://md.psych.bio.uni-goettingen.de/mv/data/virt/v_ei.txt")
library(psych)
pc.2 <- psych::principal(dd, rotate='none', nfactors=2)
# summary and Chi^2 model test
pc.2
## Principal Components Analysis
## Call: psych::principal(r = dd, nfactors = 2, rotate = "none")
## Standardized loadings (pattern matrix) based upon correlation matrix
##       PC1   PC2   h2   u2 com
## i1   0.37  0.56 0.45 0.55 1.7
## i2   0.78 -0.22 0.65 0.35 1.2
## i3   0.38  0.58 0.49 0.51 1.7
## i4  -0.71  0.34 0.61 0.39 1.4
## i5   0.37  0.48 0.36 0.64 1.9
## i6  -0.72  0.31 0.61 0.39 1.4
## i7   0.28  0.28 0.16 0.84 2.0
## i8   0.77 -0.09 0.60 0.40 1.0
## i9   0.42  0.53 0.46 0.54 1.9
## i10 -0.78  0.22 0.65 0.35 1.2
## i11  0.36  0.53 0.41 0.59 1.8
## i12 -0.70  0.32 0.59 0.41 1.4
## 
##                        PC1  PC2
## SS loadings           4.10 1.95
## Proportion Var        0.34 0.16
## Cumulative Var        0.34 0.50
## Proportion Explained  0.68 0.32
## Cumulative Proportion 0.68 1.00
## 
## Mean item complexity =  1.5
## Test of the hypothesis that 2 components are sufficient.
## 
## The root mean square of the residuals (RMSR) is  0.08 
##  with the empirical chi square  90.97  with prob <  2.7e-05 
## 
## Fit based upon off diagonal values = 0.93
# original correlation table, that will be reproduced more or less by PCA
head(round(cor(dd), 2))
##       i1    i2    i3    i4    i5    i6    i7    i8    i9   i10   i11   i12
## i1  1.00  0.18  0.35 -0.06  0.17 -0.23  0.18  0.14  0.43 -0.08  0.30 -0.11
## i2  0.18  1.00  0.14 -0.48  0.18 -0.52  0.21  0.57  0.18 -0.61  0.12 -0.60
## i3  0.35  0.14  1.00 -0.07  0.30 -0.11  0.13  0.25  0.34 -0.25  0.33 -0.05
## i4 -0.06 -0.48 -0.07  1.00 -0.12  0.63 -0.12 -0.45 -0.11  0.53 -0.15  0.54
## i5  0.17  0.18  0.30 -0.12  1.00 -0.04  0.18  0.31  0.26 -0.13  0.33 -0.11
## i6 -0.23 -0.52 -0.11  0.63 -0.04  1.00 -0.04 -0.47 -0.18  0.58 -0.04  0.45
# get the reproduced correlation matrix, which is calculated on base of the loadings
# diagonal are the communalities
head(round(factor.model(pc.2$loadings), 2))
##       i1    i2    i3    i4    i5    i6    i7    i8    i9   i10   i11   i12
## i1  0.45  0.16  0.47 -0.07  0.40 -0.09  0.26  0.23  0.45 -0.16  0.43 -0.08
## i2  0.16  0.65  0.17 -0.62  0.18 -0.63  0.15  0.62  0.21 -0.65  0.17 -0.61
## i3  0.47  0.17  0.49 -0.07  0.42 -0.09  0.27  0.24  0.47 -0.17  0.45 -0.08
## i4 -0.07 -0.62 -0.07  0.61 -0.09  0.61 -0.10 -0.57 -0.11  0.62 -0.07  0.60
## i5  0.40  0.18  0.42 -0.09  0.36 -0.11  0.24  0.24  0.41 -0.18  0.39 -0.10
## i6 -0.09 -0.63 -0.09  0.61 -0.11  0.61 -0.11 -0.58 -0.13  0.63 -0.09  0.60
# get the residuals. These are the differences between original and reproduced correlation matrix
pc.diff <- cor(dd) - factor.model(pc.2$loadings)
head(round(pc.diff, 2))
##       i1    i2    i3    i4    i5    i6    i7    i8    i9   i10   i11   i12
## i1  0.55  0.02 -0.12  0.01 -0.23 -0.14 -0.08 -0.09 -0.02  0.08 -0.13 -0.03
## i2  0.02  0.35 -0.03  0.15  0.00  0.11  0.06 -0.05 -0.02  0.04 -0.04  0.02
## i3 -0.12 -0.03  0.51  0.00 -0.12 -0.01 -0.14  0.00 -0.14 -0.08 -0.11  0.04
## i4  0.01  0.15  0.00  0.39 -0.03  0.02 -0.02  0.12  0.00 -0.09 -0.07 -0.06
## i5 -0.23  0.00 -0.12 -0.03  0.64  0.07 -0.06  0.07 -0.15  0.05 -0.05  0.00
## i6 -0.14  0.11 -0.01  0.02  0.07  0.39  0.07  0.11 -0.05 -0.04  0.05 -0.15
rm(pc.diff)
# get the same via call to factor.residuals()
# diagonal are the uniquenesses.
pc.diff.2 <- factor.residuals(cor(dd), pc.2$loadings)
head(round(pc.diff.2, 2))
##       i1    i2    i3    i4    i5    i6    i7    i8    i9   i10   i11   i12
## i1  0.55  0.02 -0.12  0.01 -0.23 -0.14 -0.08 -0.09 -0.02  0.08 -0.13 -0.03
## i2  0.02  0.35 -0.03  0.15  0.00  0.11  0.06 -0.05 -0.02  0.04 -0.04  0.02
## i3 -0.12 -0.03  0.51  0.00 -0.12 -0.01 -0.14  0.00 -0.14 -0.08 -0.11  0.04
## i4  0.01  0.15  0.00  0.39 -0.03  0.02 -0.02  0.12  0.00 -0.09 -0.07 -0.06
## i5 -0.23  0.00 -0.12 -0.03  0.64  0.07 -0.06  0.07 -0.15  0.05 -0.05  0.00
## i6 -0.14  0.11 -0.01  0.02  0.07  0.39  0.07  0.11 -0.05 -0.04  0.05 -0.15
rm(pc.diff.2)

In der Diagonalen der reproduzierten Korrelationstabelle stehen die Kommunalitäten. In der Diagonalen der Differenzen (Residuen) stehen die spezifischen Anteile (Uniquenesses).

Ein Maß für die Qualität des Fits kann auf diesen Residuen aufbauen. Die Residuen im Verhältnis zur Höhe der Korrelation sind eine Grundidee für einen Fit-Index. Die Summe der quadrierten Residuen im Verhältnis zur Summe der quadrierten Korrelationen, von 1 abgezogen, ist der Wert hinter ‘Fit based upon off diagonal values = …’ Werte über .95 sprechen für einen guten Fit.

Der Likelihood-Quotienten-Test prüft auf Signifikanz ob die Anzahl der Faktoren ausreicht, um die Daten genügend zu erklären. Er setzt Normalverteilung voraus. Geprüft wird die 0-Hypothese, dass die Daten und das Modell mit k Faktoren statistisch gleich sind. Dabei hat die Aufnahme eines Faktors ihren ‘Preis’. Die Anzahl der Elementgleichungen geht in die Modellprüfung mit ein.

Hintergrundartikel von Manhart & Hunger (2008)

Tuckers Kongruenzkoeffizient

Der Kongruenzkoeffizient von Tucker dient dem Vergleich von zwei Faktoranalysen (z. B. nach Split einer Stichprobe), um die Stabilität der Faktorstruktur zu beschreiben. Analog zum Korrelationskoeffizienten interpretierbar. Koeffizienten sollten deutlich über .80 liegen. Befehl: psych::factor.congruence()

paper

Lorenzo-Seva1 & ten Berge (2006) “Tucker’s Congruence Coefficient as a Meaningful Index of Factor Similarity” Artikel oder lokale Kopie über die Bewertung der Höhe von Tuckers Kongruenzkoeffizient.

The congruence coefficient is the cosine of the angle between the two vectors, and can be interpreted as a standardized measure of proportionality of elements in both vectors. It is evaluated as \[ \phi(x,y) = \frac{\sum{x_i, y_i} } {\sqrt{\sum{x_i^2}\sum{y_i^2}}} \] where \(x_i\) and \(y_i\) are the loadings of variable \(i\) on factor \(x\) and \(y\), respectively, \(i=1,...,n\)

“Our results suggest that a value in the range .85–.94 corresponds to a fair similarity, while a value higher than .95 implies that the two factors or components compared can be considered equal.”

# dd <- read.delim(file="http://md.psych.bio.uni-goettingen.de/mv/data/div/werner-fa.txt")
dd <- read.delim("http://md.psych.bio.uni-goettingen.de/mv/data/virt/v_ei.txt")
# we split the sample into two equal sized subsamples
set.seed(123)
dd$split <- FALSE
dd$split[sample(1:nrow(dd), nrow(dd)/2)] <- TRUE
dd.1 <- dd[dd$split,1:ncol(dd)-1]
dd.2 <- dd[!dd$split,1:ncol(dd)-1]


# we apply ML-FA to the two subsamples
require(psych)
fa.1 <- psych::fa(dd.1, 
    nfactors=2,
    n.obs = nrow(dd.1),
  SMC=TRUE,
  fm="ml",
  rotate="none",
  max.iter=100
  )
fa.2 <- psych::fa(dd.2, 
    nfactors=2,
    n.obs = nrow(dd.2),
  SMC=TRUE,
  fm="ml",
  rotate="none",
  max.iter=100
  )

# we compare it
psych::factor.congruence(fa.1, fa.2)
##       ML1  ML2
## ML1 -0.97 0.28
## ML2  0.11 0.68

Ausflug: Abgrenzung PCA und FA

Hierauf wird auch in den einzelnen Units eingegangen.

Principal component analysis involves extracting linear composites of observed variables.

Factor analysis is based on a formal model predicting observed variables from theoretical latent factors.

In psychology these two techniques are often applied in the construction of multi-scale tests to determine which items load on which scales. They typically yield similar substantive conclusions (for a discussion see Comrey (1988) Factor-Analytic Methods of Scale Development in Personality and Clinical Psychology). This helps to explain why some statistics packages seem to bundle them together. I have also seen situations where “principal component analysis” is incorrectly labelled “factor analysis”.

In terms of a simple rule of thumb, I’d suggest that you:

Run factor analysis if you assume or wish to test a theoretical model of latent factors causing observed variables.

Run principal component analysis If you want to simply reduce your correlated observed variables to a smaller set of important independent composite variables.

quelle

Principal Component Analysis (PCA) and Common Factor Analysis (CFA) are distinct methods. Often, they produce similar results and PCA is used as the default extraction method in the SPSS Factor Analysis routines. This undoubtedly results in a lot of confusion about the distinction between the two.

The bottom line is that these are two different models, conceptually. In PCA, the components are actual orthogonal linear combinations that maximize the total variance. In FA, the factors are linear combinations that maximize the shared portion of the variance–underlying “latent constructs”. That’s why FA is often called “common factor analysis”. FA uses a variety of optimization routines and the result, unlike PCA, depends on the optimization routine used and starting points for those routines. Simply there is not a single unique solution.

In R, the factanal() function provides CFA with a maximum likelihood extraction. So, you shouldn’t expect it to reproduce an SPSS result which is based on a PCA extraction. It’s simply not the same model or logic. I’m not sure if you would get the same result if you used SPSS’s Maximum Likelihood extraction either as they may not use the same algorithm.

For better or for worse in R, you can, however, reproduce the mixed up “factor analysis” that SPSS provides as its default. Here’s the process in R. With this code, I’m able to reproduce the SPSS Principal Component “Factor Analysis” result using this dataset. (With the exception of the sign, which is indeterminate). That result could also then be rotated using any of R’s available rotation methods.

# Load the base dataset attitude to work with.
data(attitude)
# Compute eigenvalues and eigenvectors of the correlation matrix.
pfa.eigen<-eigen(cor(attitude))
# Print and note that eigenvalues are those produced by SPSS.
# Also note that SPSS will extract 2 components as eigenvalues > 1 = 2
pfa.eigen$values
## [1] 3.7163758 1.1409219 0.8471915 0.6128697 0.3236728 0.2185306 0.1404378
    # set a value for the number of factors (for clarity)
    factors<-2
    # Extract and transform two components.
    pfa.eigen$vectors [ , 1:factors ]  %*% 
+ diag ( sqrt (pfa.eigen$values [ 1:factors ] ),factors,factors )
##           [,1]       [,2]
## [1,] 0.7961866  0.4239721
## [2,] 0.8492648  0.3563602
## [3,] 0.6839314  0.1022845
## [4,] 0.8261764  0.0481755
## [5,] 0.8619753 -0.1913818
## [6,] 0.3573175 -0.6436979
## [7,] 0.5832712 -0.6086213

Beispiele Übungen / Exercises

bei den jeweiligen Einzelverfahren

Example BFI data

library(dplyr)
library(psych)
# get data
dd <- read.delim("http://md.psych.bio.uni-goettingen.de/mv/data/div/bfi_rs1.txt")
bfi_10_items2 <- c("bfi.k.2.i1","bfi.k.2.i7","bfi.k.2.i8","bfi.k.2.i9","bfi.k.2.i21","bfi.k.2.i16", "bfi.k.2.i2","bfi.k.2.i3","bfi.k.2.i19","bfi.k.2.i15")

bfi.items <- dd[bfi_10_items2]
# just to countercheck wheather parallel analysis suggests the theoretically postulated 5 factors
items.parallel <- fa.parallel(bfi.items, fa="pc")

## Parallel analysis suggests that the number of factors =  NA  and the number of components =  4
# ... no, 4 components are suggested by parallel analysis

# PCA with varimax rotation of BFI-10
# pca with 5 components that are postulated by BFI model, varimax rotated
pc <- psych::principal(bfi.items, rotate='varimax', nfactors=5)
print.psych(pc, cut=0.3, sort=F)
## Principal Components Analysis
## Call: psych::principal(r = bfi.items, nfactors = 5, rotate = "varimax")
## Standardized loadings (pattern matrix) based upon correlation matrix
##               RC1   RC2   RC4   RC3   RC5   h2   u2 com
## bfi.k.2.i1   0.82                         0.70 0.30 1.1
## bfi.k.2.i7               0.72             0.55 0.45 1.1
## bfi.k.2.i8         0.81                   0.72 0.28 1.2
## bfi.k.2.i9         0.31       -0.66  0.31 0.74 0.26 2.6
## bfi.k.2.i21                          0.86 0.75 0.25 1.0
## bfi.k.2.i16 -0.68        0.47             0.70 0.30 1.9
## bfi.k.2.i2                     0.72       0.69 0.31 1.7
## bfi.k.2.i3        -0.68  0.37             0.64 0.36 1.7
## bfi.k.2.i19  0.65              0.43       0.66 0.34 2.0
## bfi.k.2.i15 -0.33        0.57       -0.38 0.61 0.39 2.6
## 
##                        RC1  RC2  RC4  RC3  RC5
## SS loadings           1.75 1.34 1.33 1.21 1.12
## Proportion Var        0.18 0.13 0.13 0.12 0.11
## Cumulative Var        0.18 0.31 0.44 0.56 0.68
## Proportion Explained  0.26 0.20 0.20 0.18 0.17
## Cumulative Proportion 0.26 0.46 0.66 0.83 1.00
## 
## Mean item complexity =  1.7
## Test of the hypothesis that 5 components are sufficient.
## 
## The root mean square of the residuals (RMSR) is  0.11 
##  with the empirical chi square  1315.78  with prob <  2.4e-282 
## 
## Fit based upon off diagonal values = 0.47
pc$Vaccounted
##                             RC1       RC2       RC4       RC3       RC5
## SS loadings           1.7534956 1.3389434 1.3318050 1.2118364 1.1153488
## Proportion Var        0.1753496 0.1338943 0.1331805 0.1211836 0.1115349
## Cumulative Var        0.1753496 0.3092439 0.4424244 0.5636080 0.6751429
## Proportion Explained  0.2597221 0.1983200 0.1972627 0.1794933 0.1652019
## Cumulative Proportion 0.2597221 0.4580421 0.6553048 0.8347981 1.0000000
pc$loadings
## 
## Loadings:
##             RC1    RC2    RC4    RC3    RC5   
## bfi.k.2.i1   0.821                            
## bfi.k.2.i7         -0.127  0.720 -0.124       
## bfi.k.2.i8   0.167  0.813  0.106  0.128       
## bfi.k.2.i9  -0.196  0.309  0.279 -0.661  0.311
## bfi.k.2.i21                              0.856
## bfi.k.2.i16 -0.676         0.474              
## bfi.k.2.i2  -0.150  0.252         0.723  0.278
## bfi.k.2.i3         -0.681  0.369         0.176
## bfi.k.2.i19  0.648  0.140  0.157  0.430       
## bfi.k.2.i15 -0.327         0.572  0.123 -0.384
## 
##                  RC1   RC2   RC4   RC3   RC5
## SS loadings    1.753 1.339 1.332 1.212 1.115
## Proportion Var 0.175 0.134 0.133 0.121 0.112
## Cumulative Var 0.175 0.309 0.442 0.564 0.675

Check

  • Faktorenanalysen wollen eine Anzahl von Variablen auf weniger Variablen (Faktoren) reduzieren, wobei so viel Information wie möglich erhalten bleiben soll, die in den Ursprungsvariablen enthalten ist.

  • Im Kern wird versucht, die Korrelationsmatrix der Originalvariablen durch wenige Faktoren so gut wie möglich zu reproduzieren.

  • Unterscheidung PCA, FA-Varianten und CFA

  • Das Package `library(psych)´ hat speziell für die Psychologie interessante Befehle, auch im Zusammenhang mit Faktorenanalysen, in diesem Kontext

    1. B. cortest.bartlett(), KMO(), fa.parallel(), print.psych(), principal() usw.
  • Bei PCA ist erklärter Varianzanteil durch Komponenten nach Größe geordnet und unabhängig von Anzahl der extrahierten Faktoren. Auch die Factorscores bleiben bei PCA für jede Komponente gleich, unabhängig von der Menge der Komponenten. Bei eFA ändern sie sich in Abhängigkeit von der Anzahl der extrahierten Faktoren.

  • PCA: factor scores sind Linearkombinationen der Variablen und der “loadings” deren Ergebnis die individuellen Faktorwerte der Beobachtungen sind. Können auch auf neue Beobachtungen übertragen werden. Das entspricht predict() im ALM und der Befehl heißt tatsächlich auch predict.psych()

  • Parallelanalyse

  • Wir schauen uns die Ladungsmatrix an und versuchen, sie mit Inhalt zu füllen. psych::print.psych()

  • Marker-Items (Q06 für RC3) und Cross-Loadings (Q12 zwischen RC3 und RC1) in dem Beispiel unten

  • Wir interpretieren Sinn in eine Zusammenfassung von Zusammenhängen.

  • Überprüfen faktorieller Strukturen, z. B. Stabilität: eFA an mehreren Datensätzen und die vorgeschlagene Faktorenstruktur auf Ähnlichkeiten prüfen.

  • eFA vs CFA: Wenn wir eine Vorstellung der Psychologie haben, die hinter den Faktoren steckt, sollten wir eher CFAs anwenden. Mit eFA können wir nur vergleichen, ob bei unterschiedlichen Datensätzen eine ähnliche Faktorenstruktur vorgeschlagen wird. Alternative CFA kommt ist Anwendung von Strukturgleichungsmodellen (Pfadanalysen).

  • KMO und Zusammenspiel mit den anderen Bewertungs- bzw. Eignungsmaßen

require(tidyverse)
## Loading required package: tidyverse
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.0 ──
## ✓ ggplot2 3.3.3     ✓ purrr   0.3.4
## ✓ tibble  3.1.0     ✓ stringr 1.4.0
## ✓ tidyr   1.1.3     ✓ forcats 0.5.1
## ✓ readr   1.4.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x ggplot2::%+%()   masks psych::%+%()
## x ggplot2::alpha() masks psych::alpha()
## x dplyr::filter()  masks stats::filter()
## x dplyr::lag()     masks stats::lag()
require(psych)

dd <- read_delim("https://pzezula.pages.gwdg.de/data/raq.dat", delim="\t")
## 
## ── Column specification ────────────────────────────────────────────────────────
## cols(
##   .default = col_double()
## )
## ℹ Use `spec()` for the full column specifications.
# or
dd <- readr::read_tsv("http://md.psych.bio.uni-goettingen.de/mv/data/af/raq.dat")
## 
## ── Column specification ────────────────────────────────────────────────────────
## cols(
##   .default = col_double()
## )
## ℹ Use `spec()` for the full column specifications.
# are the data suitable for factorization
# testing whether a correlation matrix is factorable
psych::cortest.bartlett(dd)
## R was not square, finding R from data
## $chisq
## [1] 19334.49
## 
## $p.value
## [1] 0
## 
## $df
## [1] 253
# ... yes, correlations differ from 0
# ... but we do better 
# is the Kaiser-Meyer-Olkin KMO test of factorial adequacy.
kmo_raq <- psych::KMO(dd)
kmo_raq
## Kaiser-Meyer-Olkin factor adequacy
## Call: psych::KMO(r = dd)
## Overall MSA =  0.93
## MSA for each item = 
##  Q01  Q02  Q03  Q04  Q05  Q06  Q07  Q08  Q09  Q10  Q11  Q12  Q13  Q14  Q15  Q16 
## 0.93 0.87 0.95 0.96 0.96 0.89 0.94 0.87 0.83 0.95 0.91 0.95 0.95 0.97 0.94 0.93 
##  Q17  Q18  Q19  Q20  Q21  Q22  Q23 
## 0.93 0.95 0.94 0.89 0.93 0.88 0.77
# ... the closer the value to 1 the better, here we have good factorial adequacy

# parallel analysis
items.parallel <- fa.parallel(dd, fa="pc")

## Parallel analysis suggests that the number of factors =  NA  and the number of components =  4
pc <- psych::principal(dd, nfactors=4, scores=TRUE)

# we look at percentages of explained variance and factor loading matrix
print.psych(pc, cut=0.3, sort=F)
## Principal Components Analysis
## Call: psych::principal(r = dd, nfactors = 4, scores = TRUE)
## Standardized loadings (pattern matrix) based upon correlation matrix
##       RC3   RC1   RC4   RC2   h2   u2 com
## Q01        0.50  0.36       0.43 0.57 2.4
## Q02       -0.34        0.54 0.41 0.59 1.7
## Q03       -0.57        0.37 0.53 0.47 2.3
## Q04  0.32  0.52  0.31       0.47 0.53 2.4
## Q05  0.32  0.43             0.34 0.66 2.5
## Q06  0.80                   0.65 0.35 1.0
## Q07  0.64  0.33             0.55 0.45 1.7
## Q08              0.83       0.74 0.26 1.1
## Q09                    0.65 0.48 0.52 1.3
## Q10  0.55                   0.33 0.67 1.2
## Q11              0.75       0.69 0.31 1.5
## Q12  0.47  0.52             0.51 0.49 2.1
## Q13  0.65                   0.54 0.46 1.6
## Q14  0.58  0.36             0.49 0.51 1.8
## Q15  0.46                   0.38 0.62 2.6
## Q16  0.33  0.51  0.31       0.49 0.51 2.6
## Q17              0.75       0.68 0.32 1.5
## Q18  0.68  0.33             0.60 0.40 1.5
## Q19       -0.37        0.43 0.34 0.66 2.2
## Q20        0.68             0.48 0.52 1.1
## Q21        0.66             0.55 0.45 1.5
## Q22                    0.65 0.46 0.54 1.2
## Q23                    0.59 0.41 0.59 1.4
## 
##                        RC3  RC1  RC4  RC2
## SS loadings           3.73 3.34 2.55 1.95
## Proportion Var        0.16 0.15 0.11 0.08
## Cumulative Var        0.16 0.31 0.42 0.50
## Proportion Explained  0.32 0.29 0.22 0.17
## Cumulative Proportion 0.32 0.61 0.83 1.00
## 
## Mean item complexity =  1.8
## Test of the hypothesis that 4 components are sufficient.
## 
## The root mean square of the residuals (RMSR) is  0.06 
##  with the empirical chi square  4006.15  with prob <  0 
## 
## Fit based upon off diagonal values = 0.96
# as usual in summaries print psych gives us a visualization of result objects properties like
pc$Vaccounted
##                             RC3       RC1       RC4       RC2
## SS loadings           3.7272497 3.3434674 2.5509149 1.9511936
## Proportion Var        0.1620543 0.1453681 0.1109093 0.0848345
## Cumulative Var        0.1620543 0.3074225 0.4183318 0.5031663
## Proportion Explained  0.3220691 0.2889067 0.2204228 0.1686013
## Cumulative Proportion 0.3220691 0.6109759 0.8313987 1.0000000
pc$loadings
## 
## Loadings:
##     RC3    RC1    RC4    RC2   
## Q01  0.240  0.497  0.356       
## Q02        -0.337         0.544
## Q03 -0.202 -0.566 -0.180  0.368
## Q04  0.319  0.517  0.314       
## Q05  0.319  0.430  0.238       
## Q06  0.800                     
## Q07  0.638  0.328  0.155       
## Q08  0.131  0.168  0.833       
## Q09        -0.203  0.118  0.648
## Q10  0.550         0.130 -0.123
## Q11  0.262  0.206  0.747 -0.142
## Q12  0.472  0.523              
## Q13  0.647  0.234  0.228 -0.100
## Q14  0.578  0.360  0.136       
## Q15  0.459  0.217  0.292 -0.188
## Q16  0.333  0.515  0.313 -0.116
## Q17  0.271  0.223  0.747       
## Q18  0.684  0.328  0.127       
## Q19 -0.146 -0.371         0.428
## Q20         0.677        -0.142
## Q21  0.286  0.661  0.160       
## Q22 -0.191                0.645
## Q23         0.173 -0.199  0.585
## 
##                  RC3   RC1   RC4   RC2
## SS loadings    3.727 3.343 2.551 1.951
## Proportion Var 0.162 0.145 0.111 0.085
## Cumulative Var 0.162 0.307 0.418 0.503
# we can access the factor scores of our observations
head(pc$scores)
##             RC3         RC1        RC4        RC2
## [1,] -0.1066865  0.93003207  1.8266534  0.4592970
## [2,]  0.5827147  0.18940296  0.0413915 -0.2934021
## [3,]  0.5473302 -0.02775712 -0.1998143  0.9714979
## [4,] -0.7460157 -0.72254964  0.6869656  0.1867694
## [5,] -0.2518823  0.51410587  0.6336317 -0.6834459
## [6,] -1.9164897  0.27320273  0.6815885  0.5265475
# ... or even add them to our data matrix
dd.e <- cbind(dd, pc$scores)
head(dd.e)
##   Q01 Q02 Q03 Q04 Q05 Q06 Q07 Q08 Q09 Q10 Q11 Q12 Q13 Q14 Q15 Q16 Q17 Q18 Q19
## 1   4   5   2   4   4   4   3   5   5   4   5   4   4   4   4   3   5   4   3
## 2   5   5   2   3   4   4   4   4   1   4   4   3   5   3   2   3   4   4   3
## 3   4   3   4   4   2   5   4   4   4   4   3   3   4   2   4   3   4   3   5
## 4   3   5   5   2   3   3   2   4   4   2   4   4   4   3   3   3   4   2   4
## 5   4   5   3   4   4   3   3   4   2   4   4   3   3   4   4   4   4   3   3
## 6   4   5   3   4   2   2   2   4   2   3   4   2   3   3   1   4   3   1   5
##   Q20 Q21 Q22 Q23        RC3         RC1        RC4        RC2
## 1   4   4   4   1 -0.1066865  0.93003207  1.8266534  0.4592970
## 2   2   2   2   4  0.5827147  0.18940296  0.0413915 -0.2934021
## 3   2   3   4   4  0.5473302 -0.02775712 -0.1998143  0.9714979
## 4   2   2   2   3 -0.7460157 -0.72254964  0.6869656  0.1867694
## 5   2   4   2   2 -0.2518823  0.51410587  0.6336317 -0.6834459
## 6   1   3   5   2 -1.9164897  0.27320273  0.6815885  0.5265475
# we can even predict factor scores for new observations
dd.n <- rbind(dd[1,],
  c(3,   4,   4,   2,   2,   1,   1,   4,   3,   3,   3,   3,   2,   3,   4,   3,   2,   2,   4,   1,   1,   4,   2), # is exactly equal to observation 22 of dd
  c(1,   2,   4,   4,   3,   1,   2,   4,   3,   4,   3,   2,   2,   1,   2,   3,   3,   3,   4,   2,   2,   3,   3)
)
dd.n
## # A tibble: 3 x 23
##     Q01   Q02   Q03   Q04   Q05   Q06   Q07   Q08   Q09   Q10   Q11   Q12   Q13
##   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1     4     5     2     4     4     4     3     5     5     4     5     4     4
## 2     3     4     4     2     2     1     1     4     3     3     3     3     2
## 3     1     2     4     4     3     1     2     4     3     4     3     2     2
## # … with 10 more variables: Q14 <dbl>, Q15 <dbl>, Q16 <dbl>, Q17 <dbl>,
## #   Q18 <dbl>, Q19 <dbl>, Q20 <dbl>, Q21 <dbl>, Q22 <dbl>, Q23 <dbl>
predict.psych(pc, dd.n[2,], dd)
##           RC3       RC1        RC4        RC2
## [1,] -1.71775 -0.669199 -0.1793628 -0.5121014
dd.e[22,]
##    Q01 Q02 Q03 Q04 Q05 Q06 Q07 Q08 Q09 Q10 Q11 Q12 Q13 Q14 Q15 Q16 Q17 Q18 Q19
## 22   3   4   4   2   2   1   1   4   3   3   3   3   2   3   4   3   2   2   4
##    Q20 Q21 Q22 Q23      RC3       RC1        RC4        RC2
## 22   1   1   4   2 -1.71775 -0.669199 -0.1793628 -0.5121014
pc.n <- predict.psych(pc, dd.n, dd)
pc.n
##             RC3         RC1        RC4        RC2
## [1,] -0.1066865  0.93003207  1.8266534  0.4592970
## [2,] -1.7177495 -0.66919901 -0.1793628 -0.5121014
## [3,] -2.0493875 -0.02482569 -0.3172870 -1.0614646
# observation 22 of dd had the same values as observation 2 in dd.n
pc$scores[22,]
##        RC3        RC1        RC4        RC2 
## -1.7177495 -0.6691990 -0.1793628 -0.5121014

Screencast

  • Factor analysis - check - what they have in common and their differences StudIP - ownCloud

Version: 17 Juni, 2021 10:04