PLS SEM mit R / seminr 1:
Grundlagen/Modellschätzung

Arndt Regorz, Dipl. Kfm. & MSc. Psychologie, 30.09.2023

Partial Least Squares Strukturgleichungsmodellierung (PLS SEM) kann für bestimmte Fragestellungen eine gute Alternative zum traditionellen kovarianzbasierten SEM (mit Programmen wie AMOS, MPlus, R lavaan) sein.

Dies ist das erste in einer Serie von Tutorials, die Ihnen zeigen, wie Sie mit R ein PLS SEM Modell schätzen können. Dabei wird das R Package seminr verwendet.

Video



(Hinweis: Mit Anklicken des Videos wird ein Angebot des Anbieters YouTube genutzt.)


Überblick

Um ein PLS SEM-Modell mit seminr zu schätzen, gibt es drei wesentliche Schritte:

  • Aufstellen der Messmodelle (outer model)
  • Aufstellen des Strukturmodells (inner model)
  • Schätzung des Modells

Diese drei Schritte werden nachfolgend erklärt. Zusätzlich muss noch die Modellgüte beurteilt werden (wie gut passen die Messmodelle, wie gut passt das Strukturmodell?). Dazu gibt es gesonderte Tutorials:

Als Beispiel wird in diesem Tutorial ein Datensatz verwendet, der im lavaan Modul eingebaut ist, PoliticalDemocracy. Dieser ist für Sie verfügbar, wenn Sie zusätzlich zu seminr auch lavaan installieren und laden, so dass Sie die Berechnungen aus diesem Tutorial auch selbst nachvollziehen können.

Im Datensatz PoliticalDemocracy wird der Zusammenhang zwischen der Industrialisierung von Entwicklungsländern in 1960 mit dem Zustand deren Demokratie in den Jahren 1960 und 1965 untersucht:

Grafik PLS SEM 1 Bild 1

1. Aufstellen der Messmodelle

Die Messmodelle definieren, wie die latenten Konstrukte aus den Indikatorvariablen geschätzt werden. Dabei gibt es zwei grundsätzliche Typen von Messmodellen: Reflektive und Formative. Reflektierende Indikatoren in SEM repräsentieren beobachtete Variablen, die ein zugrunde liegendes Konstrukt messen. Veränderungen im Konstrukt beeinflussen die reflektierenden Indikatoren, und sie sollten eng miteinander zusammenhängen (in der Modellgrafik gehen hier die Pfeile vom Konstrukt zu den Indikatoren). Formative Indikatoren hingegen repräsentieren beobachtete Variablen, die das Konstrukt beeinflussen (hier gehen in der Modellgrafik die Pfeile von den Indikatoren zum Konstrukt). In solchen Modellen wird keine starke Zusammengehörigkeit zwischen den Indikatoren erwartet. Die Wahl zwischen den beiden hängt davon ab, wie das Konstrukt in der Forschungskonzeption betrachtet wird.

Reflektives Messmodell

Hier ist ein mögliches reflektives Messmodell für die drei Konstrukte des Beispieldatensatzes:

measure_poldem <- constructs(
reflective("indus", multi_items("x", 1:3)),
reflective("dem60", multi_items("y", 1:4)),
reflective("dem65", multi_items("y", 5:8)) )

Die construct() Funktion enthält die verschiedenen Konstrukte des Datensatzes.

Für jede einzelne latente Variable wird hier die reflective() Funktion verwendet. Dort wird zunächst der – selbst gewählte – Name des Konstrukts in Anführungszeichen verwendet, anschließend wird angegeben, welche Items das Konstrukt messen.

Dabei wird hier zur Vereinfachung die multi_items() Funktion verwendet. Dort wird zunächst der für alle Itemnamen gleiche Teil genannt, und anschließend die Nummernrange der Itemnummern. Wenn man z.B. die drei Items „depr1“, „depr2“ und „depr3“ hätte, dann wäre der Funktionsaufruf multi_items("depr", 1:3).

Man kann aber alternativ auch die Itemnamen direkt als Vektor eingeben. Der folgende Code ist insoweit also äquivalent zum o.g. Code:

# alternative Definition: measure_poldem <- constructs(
reflective("indus", c("x1", "x2", "x3")),
reflective("dem60", c("y1", "y2", "y3", "y4")),
reflective("dem65", c("y5", "y6", "y7", "y8")) )

Als weitere Funktion gibt es noch single_item("....."), wenn man ein Konstrukt hat, das nur durch ein einziges Item gemessen werden soll.

Formatives Messmodell

Wenn wir die gleichen Variablen formativ messen wollten, dann wäre dies hier ein möglicher Code:

measure_poldem_f <- constructs(
composite("indus", multi_items("x", 1:3), weights = mode_B),
composite("dem60", multi_items("y", 1:4), weights = mode_B),
composite("dem65", multi_items("y", 5:8), weights = mode_B) )

Hier verwenden wir innerhalb der constructs() Funktion statt der reflective() Funktion die composite() Funktion und wir geben als zusätzlichen Parameter noch weights = mode_B an.

Grundsätzlich ist es auch möglich, innerhalb eines Modells beide Formen von Messmodellen zu mixen – es kann also sein, dass einige Ihrer latenten Variablen formativ gemessen werden und einige reflektiv.

2. Aufstellen des Strukturmodells

Nachdem wir ein Messmodell definiert haben, definieren wir auch ein Strukturmodell, also den Zusammenhang zwischen den von uns oben definierten Konstrukten.

struct_poldem <- relationships(
paths(from = "indus", to = "dem60"),
paths(from = c("indus", "dem60"), to = "dem65") )

Die Zuweisung beginnt mit der relationsships() Funktion. In dieser werden die gerichteten Pfade angegeben. Man kann das auf unterschiedliche Weise machen. Ich schreibe jeweils für jede endogene Variable (also für jede Variable, auf die mindestens ein gerichteter Strukturpfad zeigt) eine Zeile, bei der ich hinter from die Variablen aufführe, von denen Pfeile auf die betreffende Variable (hinter „to“) zeigen.

3. Schätzung des Modells

Für die Schätzung des Modells nutzen wir die estimate_pls() Funktion. Wir geben an den verwendeten Dataframe, die von uns oben erstellte Definition des Messmodells, die von uns erstellte Definition des Stukturmodells und die Berechnungsmethode für die inner_weights (Strukturpfade).

poldem_pls <- estimate_pls(
data = PoliticalDemocracy,
measurement_model = measure_poldem,
structural_model = struct_poldem,
inner_weights = path_weighting )

Es gibt noch weitere mögliche Parameter, beispielweise für den Umgang mit fehlenden Daten. Diese können Sie sich wie bei R üblich über die Hilfe anzeigen lassen:

? estimate_pls

Als Output für unseren Beispieldatensatz bekommen wir (hier im Beispiel bei Verwendung der reflektiven Definition des Messmodells, der Ablauf ist beim formativen Messmodell aber gleich, nur dass oben unter „measurement_model“ dann ein formatives Messmodell übergeben werden muss):

Results from package seminr (2.3.2)

Path Coefficients:
dem60 dem65
R^2 0.193 0.977
AdjR^2 0.182 0.977
indus 0.439 0.159
dem60 . 0.909

Reliability:
alpha rhoC AVE rhoA
indus 0.944 0.945 0.853 0.954
dem60 0.870 0.873 0.634 0.882
dem65 0.885 0.885 0.658 0.886

Alpha, rhoC, and rhoA should exceed 0.7 while AVE should exceed 0.5

Unter den „Path Coefficients“ finden wir das R² und das adjustierte R² der zu erklärenden Variablen sowie die standardisierten Pfadgewichte für die drei geschätzten Pfade:
Industrialisierung -> Demokratie1960: 0.439
Industrialisierung -> Demokratie1965: 0.159
Demokratie ->Demokratie1965: 0.909

Wenn man dieses Ergebnis mit der Schätzung durch andere PLS SEM Programme vergleichen möchte (z.B. mit SmartPLS), dann ist es wichtig zu wissen, dass seminr bei reflektiven Messmodellen die sog. „consistent PLS“ Schätzung als Verfahren anwendet, die man z.B. in SmartPLS gesondert einstellen müsste, um zu gleichen Ergebnissen zu kommen.

Auf den unteren Bereich zur Reliabilität gehe ich hier noch nicht ein, zur Bewertung der Modellgüte gibt es von mir gesonderte Tutorials (Links siehe am Anfang des Tutorials).

Wir können uns auch eine Grafik mit den Ergebnissen der Modellschätzung anzeigen lassen:

plot(poldem_pls)

Grafik PLS SEM 1 Bild 2

Was wir hier nicht sehen, anders als bei vielen andere statistischen Auswertungen, sind p-Werte. Das liegt daran, dass PLS SEM keine Verteilungsannahmen macht (anders als viele Verfahren, die von der Normalverteilung ausgehen). Daher können wir hier auch keine Teststatistik und keine p-Werte ablesen.

Um im Rahmen von PLS SEM Signifikanztests durchführen zu können, wird das Verfahren Bootstrapping genutzt, einem Verfahren mit zufälligem Resampling. Dieses Verfahren hat keine Verteilungsannahmen. Beim Aufruf mit der bootstrap_model() Funktion übergeben wir das Ergebnis unserer Modellschätzung, die von uns gewünschte Anzahl der Bootstrapstichproben (ich bevorzuge hier mit 10,000 einen recht hohen Wert, auch wenn das dann etwas länger dauert mit der Schätzung, um so stabilere Ergebnisse zu bekommen) sowie optional auch noch ein Seed-Wert, der dafür sorgt, dass Sie bei jedem Aufruf mit den gleichen Daten auch die gleichen Ergebnisse bekommen (welcher Wert hinter seed = steht, ist dabei egal, solange es jeweils bei jedem Aufruf der gleiche Wert ist).

poldem_pls_boot <- bootstrap_model(poldem_pls, nboot = 10000, seed = 12345) summary(poldem_pls_boot, alpha = 0.05)

Jetzt bekommen wir gebootstrappte Konfidenzintervalle. Dabei zeigt ein Konfidenzintervall dann ein signifikantes Ergebnis an, wenn das Konfidenzintervall die Null nicht mit einschließt (wenn also entweder beide Grenzen des Konfidenzintervalls negativ oder beide Grenzen positiv sind). Hier als erster Teil des Outputs die Ergebnisse für die drei strukturellen Pfade:

summary(poldem_pls_boot, alpha = 0.05)$bootstrapped_paths
Original Est. Bootstrap Mean Bootstrap SD T Stat. 2.5% CI 97.5% CI
indus -> dem60 0.439 0.439 0.109 4.029 0.215 0.638
indus -> dem65 0.159 0.157 0.063 2.516 0.032 0.281
dem60 -> dem65 0.909 0.910 0.048 18.834 0.805 0.993

Die Konfidenzintervalle für alle drei Pfade schließen jeweils die Null nicht mit ein, sie sind also jeweils signifikant von Null verschieden.

Bevor wir diese Ergebnisse jedoch inhaltlich interpretieren dürfen, müssen wir zunächst noch die Modellgüte prüfen. Siehe dazu Tutorials:

4. Literatur

Partial Least Squares Structural Equation Modeling (PLS-SEM) Using R. (n.d.). github. https://sem-in-r.github.io/seminr/