::p_load(lme4, nlme, tidyverse, lmerTest, gridExtra, ggplot2) pacman
1 Modelle mit Level-1-Prädiktoren
In diesem Kapitel behandeln wir Hierarchische Lineare Modelle mit Level-1-Prädiktoren. Aufbau und Systematik der Darstellung orientieren sich am Lehrbuch “Statistik und Forschungsmethoden” von Eid et al. (2017).
Es handelt sich um Modelle mit einer 2-Ebenen-Struktur (Individuen genestet in Gruppen), und zunächst werden nur Modelle ohne jede Prädiktorvariable (Intercept-Only-Modell) sowie Modelle mit ausschliesslich Prädiktorvariablen auf Level 1 (Random-Intercept-Modell und Random-Coefficients-Modell) behandelt.
Laden der benötigten Packages:
1.1 HLM Packages
Zu Beginn ein kurzer Überblick über die beiden Packages, die wir in diesem Kurs für Hierarchische Lineare Modelle benutzen werden.
nlme
Dies ist das ursprüngliche HLM- oder Mixed-Model-Package. Es hat mehr Optionen, insbesondere im Hinblick auf die Struktur der Level-1-Fehler bei Daten mit wiederholten Messungen. Wir verwenden nlme
im Kapitel zu HLM-Modellen mit Messwiederholung. Die Syntax-Struktur wird dort behandelt.
lme4
Dieses modernere HLM-Package ist sehr gut geeignet für “normale” Hierarchische Lineare Modelle mit genesteten Gruppen. Wir verwenden es im Folgenden für die Analysen der Modelle mit Level-1- und Level-2-Prädiktoren.
Die “lme4”-Syntax baut auf der model syntax auf, die wir schon von lm()
für “normale” Regressionsmodelle kennen. Also:
lm(formula = AbhängigeVariable ~ UnabhängigeVariable, data = dataframe)
Bei der Funktion lmer()
(aus dem Package lme4
) kommt die Spezifizierung der Gruppenvariable hinzu, und welche zufälligen Effekte geschätzt werden sollen. Die Syntax in der Klammer unterscheidet die lmer()
-Syntax von der simplen Syntax der lm()
-Funktion. In der Klammer wird links vom |
spezifiziert, welche zufälligen Effekte geschätzt werden sollen. Rechts des |
steht die Variable, die die Gruppenstruktur (Nestungsstruktur) der Daten definiert.
Eine 1
im linken Teil der Klammer bedeutet, dass Random Intercepts geschätzt werden sollen. Wenn die Unabhängige Variable (also die Prädiktorvariable) auch links vor dem |
steht, bedeutet dies, dass zusätzlich auch Random Slopes geschätzt werden.
Was bedeutet also folgende Syntax?
lmer(data = dataframe, AbhängigeVariable ~ UnabhängigeVariable + (1 | Gruppenvariable))
Antwort: die Abhängige Variable (AV) wird durch die Unabhängige Variable (UV) vorhergesagt. Gleichzeitig wird der Intercept separat für jede Ausprägung der Gruppenvariable geschätzt bzw. die Varianz der Level-2-Residuen des Intercepts ist ein Parameter des Modells.
Diese Syntax wird später noch erweitert.
1.2 Daten laden und aufbereiten
Wir laden die Daten und speichern sie im Objekt df
(für “data frame”). Wir können das Datenfile direkt aus dem Internet (GitHub) herunterladen:
<- read_csv(
df url("https://raw.githubusercontent.com/methodenlehre/data/master/statistik_IV/salary-data.csv")
)
1.2.1 Beschreibung der Beispieldaten
Bei diesen Daten handelt es sich um Lohn-Daten von 20 Firmen mit je 30 Angestellten (fiktive, simulierte Daten). Zu jeder/jedem Angestellten haben wir Informationen zum Lohn (salary
, in 1000 CHF), bei welcher Firma die Person angestellt ist (company
), und wie lange die Person schon dort arbeitet (experience
). Ausserdem haben wir noch Informationen darüber, in welchem Sektor (Private
oder Public
) die Firma tätig ist (sector
). Mit dieser Variable beschäftigen wir uns aber erst in Kapitel 2.
Bevor wir uns die Daten anschauen, müssen company
und sector
noch als Faktoren definiert werden.
<- df |>
df mutate(
company = as.factor(company),
sector = as.factor(sector)
)
Jetzt können wir uns den Daten-Frame anschauen:
# Die Funktion "tail()" gibt uns die letzten 6 Zeilen aus.
tail(df)
# A tibble: 6 × 4
company experience salary sector
<fct> <dbl> <dbl> <fct>
1 Company 20 3.58 6.84 Private
2 Company 20 3.18 7.60 Private
3 Company 20 3.39 5.71 Private
4 Company 20 7.12 10.1 Private
5 Company 20 2.98 6.94 Private
6 Company 20 6.45 9.33 Private
# Die Funktion summary() gibt uns deskriptive Statistiken
# zum Datensatz aus.
summary(df)
company experience salary sector
Company 01: 30 Min. : 0.000 Min. : 4.587 Private:300
Company 02: 30 1st Qu.: 4.027 1st Qu.: 7.602 Public :300
Company 03: 30 Median : 5.170 Median : 8.564
Company 04: 30 Mean : 5.190 Mean : 8.738
Company 05: 30 3rd Qu.: 6.402 3rd Qu.: 9.840
Company 06: 30 Max. :10.000 Max. :15.418
(Other) :420
1.2.2 Group-centering des Level-1-Prädiktors experience
In diesem Kapitel zu Modellen mit Level-1-Prädiktoren werden wir uns hauptsächlich mit dem Effekt des Level-1-Prädiktors experience
auf die AV salary
beschäftigen. Dabei geht es zum einen darum, wie gross der durchschnittliche Effekt von experience
ist, das heisst der Effekt innerhalb der Firmen gemittelt über alle Firmen hinweg. Das ist die grundsätzliche Logik von HLM-Modellen (simultane Schätzung eines Regressionseffekts innerhalb mehrerer Gruppen und dann Mittelung dieses Effekts über die Gruppen hinweg). Zum anderen geht es darum, wie stark diese “Innerhalb-Effekte” zwischen den Gruppen variieren, also wie ähnlich bzw. unterschiedlich der Effekt von experience
auf salary
in den verschiedenen Gruppen ist.
Man könnte diese Modelle mit der Original-Variablen experience
als Level-1-UV schätzen (vgl. das Vorgehen bei Eid et al. (2017)). Es ist jedoch für bestimmte Aspekte der Modelle (insbesondere für spätere Modelle mit Level-2-Prädiktoren, die wir in Kapitel 2 betrachten werden) sinnvoll, wenn wir für den Level-1-Prädiktor experience
vorher ein “Group-centering” vornehmen, d.h. die Abweichung jeder Person von ihrem Gruppenmittelwert berechnen und diese in der Variablen exp_centered
speichern.
exp_centered
enthält also nur noch Informationen darüber, wieviel mehr (positiver Wert) oder weniger (negativer Wert) Erfahrung eine Person relativ zum experience
-Mittelwert ihrer Firma aufweist. Wir benutzen in diesem und im nächsten Kapitel ausschliesslich diese gruppenzentrierte Variable exp_centered
als Level-1-Prädiktor.
Wir berechnen exp_centered
mit der Pipe |>
und benutzen group_by()
und mutate()
aus dem tidyverse
-Package. Um die Berechnung durchzuführen, berechnen wir zuerst eine Gruppenmittelwerts-Variable exp_groupmean
, die wir später in Kapitel 2 noch brauchen werden und aus diesem Grund im Datensatz behalten.
# Berechnen der experience-Mittelwerte pro Gruppe (exp_groupmean),
# und der Gruppenmittelwert-zentrierten experience (exp_centered)
<- df |>
df group_by(company) |>
mutate(
exp_groupmean = mean(experience),
exp_centered = experience - exp_groupmean
|>
) ungroup()
# Jetzt können wir uns die Daten nochmals anschauen - hat alles funktioniert?
head(df)
# A tibble: 6 × 6
company experience salary sector exp_groupmean exp_centered
<fct> <dbl> <dbl> <fct> <dbl> <dbl>
1 Company 01 6.87 8.96 Private 6.37 0.496
2 Company 01 5.66 9.54 Private 6.37 -0.714
3 Company 01 4.58 7.30 Private 6.37 -1.79
4 Company 01 6.56 8.09 Private 6.37 0.186
5 Company 01 8.83 14.3 Private 6.37 2.46
6 Company 01 7.73 10.3 Private 6.37 1.36
tail(df)
# A tibble: 6 × 6
company experience salary sector exp_groupmean exp_centered
<fct> <dbl> <dbl> <fct> <dbl> <dbl>
1 Company 20 3.58 6.84 Private 5.04 -1.46
2 Company 20 3.18 7.60 Private 5.04 -1.86
3 Company 20 3.39 5.71 Private 5.04 -1.65
4 Company 20 7.12 10.1 Private 5.04 2.08
5 Company 20 2.98 6.94 Private 5.04 -2.06
6 Company 20 6.45 9.33 Private 5.04 1.41
1.3 Intercept-Only-Modell (Modell 1)
In diesem Modell ist noch keine Prädiktorvariable enthalten, es handelt sich also um eine Art Nullmodell, das nur die Variation des Achsenabschnitts zwischen den Gruppen modelliert. Und in einem Modell ohne Prädiktor beziehen sich die gruppenspezifischen Intercepts \(\beta_{0i}\) auf die Gruppenmittelwerte der AV salary
(in diesem Fall der 20 Firmen).
Level-1-Modell: \(\boldsymbol {y_{mi}=\beta_{0i}+\varepsilon_{mi}}\)
Level-2-Modell: \(\boldsymbol {\beta_{0i}=\gamma_{00} + \upsilon_{0i}}\)
Gesamtmodell: \(\boldsymbol {y_{mi} = \gamma_{00} + \upsilon_{0i}+\varepsilon_{mi}}\)
1.3.1 Modell berechnen
# Fitten des Modells und Abspeichern in der Variable intercept.only.model
<- lmer(salary ~ 1 + (1 | company), data = df, REML = TRUE)
intercept.only.model
# Abspeichern von Prädiktionen, die dieses Modell macht.
# In diesem Falle ist dies jeweils der durchschnittliche Lohn jeder Firma
# Die Funktion predict() gibt pro Zeile (in diesem Fall pro Angestelltem)
# eine Prädiktion aus, je nachdem, in welcher Firma die Person angestellt ist.
# Wir speichern diese vorhergesagten Werte, um das Modell später mit "ggplot2"
# zu veranschaulichen.
$intercept.only.preds <- predict(intercept.only.model)
df
# Output anschauen
summary(intercept.only.model)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: salary ~ 1 + (1 | company)
Data: df
REML criterion at convergence: 2158
Scaled residuals:
Min 1Q Median 3Q Max
-2.9816 -0.6506 -0.0494 0.5779 4.2131
Random effects:
Groups Name Variance Std.Dev.
company (Intercept) 0.8512 0.9226
Residual 1.9547 1.3981
Number of obs: 600, groups: company, 20
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 8.7376 0.2141 19.0000 40.82 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Mit der Funktion ranef()
kann man sich die einzelnen Random-Effects (Level-2-Residuen des Intercepts, also die \(\upsilon_{0i}\)) ausgeben lassen:
ranef(intercept.only.model)
$company
(Intercept)
Company 01 0.78965416
Company 02 1.10501807
Company 03 1.92302618
Company 04 -1.13650080
Company 05 0.95354595
Company 06 -0.95893185
Company 07 -0.01014627
Company 08 -0.25484048
Company 09 -0.65131802
Company 10 0.76848590
Company 11 -0.50626620
Company 12 0.94040709
Company 13 -0.74284383
Company 14 -0.97545482
Company 15 -1.16136931
Company 16 -0.09768008
Company 17 0.66196052
Company 18 -0.16811195
Company 19 0.35123926
Company 20 -0.82987351
with conditional variances for "company"
1.3.2 Intraklassenkorrelation
Die Intraklassenkorrelation quantifiziert das Ausmass der „Nicht-Unabhängigkeit” zwischen den Messwerten aufgrund systematischer Level-2-Unterschiede im gemessenen Merkmal. Je grösser der Anteil der Level-2-Varianz (Varianz der Gruppenmittelwerte) an der Gesamtvarianz (Summe der Level-2-Varianz und der Level-1-Varianz), desto grösser sind die Ähnlichkeiten innerhalb der Level-2-Einheiten im Vergleich zu zwischen den Level-2-Einheiten.
Die Intraklassenkorrelation ist definiert als: \(\boldsymbol {\rho = \frac{\sigma^2_{Level-2}}{\sigma^2_{Level-2}+ \sigma^2_{Level-1}}}\)
Die Intraklassenkorrelation erhält man bei Schätzung eines Nullmodells (Intercept-Only-Modell, s.o.), bei dem sowohl die (zufällige) Varianz des Intercepts (in einem Modell ohne Prädiktoren also die Varianz der Mittelwerte der Level-2-Einheiten) als auch die Level-1-Residualvarianz ausgegeben wird.
Wenn die Level-2-Varianz sich nicht überzufällig von 0 unterscheidet, spielen die Ähnlichkeiten/Abhängigkeiten innerhalb der Level-2-Einheiten keine Rolle und ein Mehrebenenmodell ist nicht unbedingt notwendig.
Intraklassenkorrelation: \(\hat{\rho} = \frac{\hat{\sigma}^2_{\upsilon_0}}{\hat{\sigma}^2_{\upsilon_0}+ \hat{\sigma}^2_\varepsilon} = \frac {0.8512}{0.8512+1.9547} = 0.303\)
-> ca. 30 % der Gesamtvarianz sind auf Level-2-(Firmen-)Unterschiede zurückzuführen.
1.3.3 Signifikanztest
Signifikanztest für \(\sigma^2_{\upsilon_0}\): Modellvergleich mit absolutem Nullmodell
Wir kennen nun also die Level-2-Varianz, aber wir haben noch keinen Signifikanztest für diesen Parameter. Diesen erhalten wir über einen Modellvergleich (Likelihood-Ratio-Test) des Intercept-Only-Modells mit einem Modell, dass keinen Random-Intercept enthält, d.h. mit einem “normalen” linearen Modell ohne Prädiktor (mit dem Gesamt-Mittelwert \(\gamma_{00}\) als einzigem Modellparameter neben der Level-1-Residualvarianz \(\sigma^2_\varepsilon\)). Dieses Modell kann man auch als “absolutes Nullmodell” bezeichnen. Wir müssen ein solches Modell nicht extra spezifizieren, sondern können die Funktion ranova()
auf das Outputobjekt intercept.only.model
anwenden. ranova()
(aus dem lme4-Hilfspackage lmerTest
) führt automatisch Modellvergleiche (nur) für Random-Effects durch, indem die vorhandenen Random-Effects Schritt für Schritt entfernt werden und das Ausgangsmodell dann mit dem so reduzierten Modell verglichen wird. In diesem Fall (Intercept-Only-Modell als Ausgangsmodell) kann nur ein Random-Effect entfernt werden, nämlich der des Intercepts.
# Vergleich des Intercept-Only-Modells mit dem "absoluten Nullmodell"
ranova(intercept.only.model)
ANOVA-like table for random-effects: Single term deletions
Model:
salary ~ (1 | company)
npar logLik AIC LRT Df Pr(>Chisq)
<none> 3 -1079.0 2164.0
(1 | company) 2 -1157.7 2319.4 157.44 1 < 2.2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Der Vergleich ist signifikant \((p<0.001)\). Wir können den p-Wert sogar noch halbieren, da es sich um einen einseitigen Test handelt. Der zu testende Parameter \(\sigma^2_{\upsilon_0}\) weist nämlich einen bounded parameter space auf (kann nicht kleiner als 0 werden). Damit haben wir eine signifikante Level-2-Varianz des Intercepts und die Verwendung eines hierarchischen linearen Modells für die folgenden Analysen ist damit angezeigt.
Weiter unten werden wir zeigen, wie Modellvergleiche mittels Likelihood-Ratio-Test auch von Hand durchgeführt werden können.
Visuell kann man sich den Vergleich zwischen dem absoluten Nullmodell und dem Intercept-Only-Modell folgendermassen vorstellen:
Code
<- "Experience in years (deviation from company mean)"
xlabel <- "Salary per month"
ylabel
# Visual comparison between the two models
<- lm(salary ~ 1, data = df)
null.model $null.model.preds <- predict(null.model)
df
ggplot(data = df, aes(x = exp_centered, y = null.model.preds)) + # , group=groupVar, colour=groupVar))+
geom_smooth(method = "lm", fullrange = TRUE, se = F, linewidth = .3) +
geom_jitter(aes(y = salary, colour = company), alpha = .2) +
labs(x = xlabel, y = ylabel) +
ggtitle("Absolutes Nullmodell") +
scale_colour_discrete() +
::theme_tufte() ggthemes
Code
$intercept.only.preds <- predict(intercept.only.model)
df
ggplot(data = df, aes(
x = exp_centered,
y = intercept.only.preds,
colour = company
+
)) geom_smooth(method = "lm", fullrange = TRUE, se = F, size = .3) +
geom_jitter(aes(y = salary), alpha = .2) +
labs(x = xlabel, y = ylabel) +
ggtitle("Intercept-Only-Modell") +
scale_colour_discrete() +
geom_abline(intercept = fixef(intercept.only.model), slope = 0) +
::theme_tufte() ggthemes
1.4 Random-Intercept-Modell (Modell 2)
Dieses Modell enthält einen Level-1-Prädiktor (exp_centered)
, der jedoch als fester Effekt konzeptualisiert wird (kein Random Slope, nur Random Intercept). Dieses Modell wird insbesondere benötigt, um den Anteil der durch den Level-1-Prädiktor erklärten Level-1-Varianz zu ermitteln (vgl. Eid et al., 2017).
Level-1-Modell:
\(\boldsymbol {y_{mi}=\beta_{0i} + \beta_{1i} \cdot x_{mi} + \varepsilon_{mi}}\)
Level-2-Modell:
\(\boldsymbol {\beta_{0i}=\gamma_{00} + \upsilon_{0i}}\)
\(\boldsymbol {\beta_{1i}=\gamma_{10}}\)
Gesamtmodell:
\(\boldsymbol {y_{mi}=\gamma_{00} + \gamma_{10} \cdot x_{mi} + \upsilon_{0i}+\varepsilon_{mi}}\)
1.4.1 Modell berechnen
# Fitten und Abspeichern des Modells
# Wenn eine Prädiktorvariable im Modell ist,
# muss der Intercept (also 1) nicht zusätzlich angegeben werden.
<- lmer(salary ~ exp_centered + (1 | company),
random.intercept.model data = df, REML = TRUE
)
# Abspeichern von Prädiktionen, die dieses Modell macht.
# Wir speichern diese Prädiktionen (vorhergesagten Werte),
# um das Modell später mit "ggplot2" zu veranschaulichen.
$random.intercept.preds <- predict(random.intercept.model)
df
# Output anschauen
summary(random.intercept.model)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: salary ~ exp_centered + (1 | company)
Data: df
REML criterion at convergence: 1871.8
Scaled residuals:
Min 1Q Median 3Q Max
-2.8261 -0.6843 -0.0048 0.5968 3.9117
Random effects:
Groups Name Variance Std.Dev.
company (Intercept) 0.8769 0.9364
Residual 1.1845 1.0884
Number of obs: 600, groups: company, 20
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 8.73760 0.21406 19.00000 40.82 <2e-16 ***
exp_centered 0.53188 0.02735 579.00000 19.45 <2e-16 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr)
exp_centerd 0.000
Die Ergebnisse zeigen, dass der Fixed-Effect von exp_centered
positiv signifikant ist \((\hat\gamma_{10} = 0.532, p < 0.001)\). Im Durchschnitt aller Firmen steigt das vorhergesagte Einkommen (salary)
also mit jedem Jahr Arbeitserfahrung um ca. 0.532 Einheiten (532 CHF) an.
1.4.2 Varianzerklärung durch Level-1-Prädiktor
Wieviel Level-1-Varianz wurde durch exp_centered
erklärt?
\(R^2_{Level-1} = \frac {\hat\sigma^2_{\varepsilon1} - \hat\sigma^2_{\varepsilon2}}{\hat\sigma^2_{\varepsilon1}} = \frac {{1.9547}-{1.1845}}{1.9547} = {0.394}\)
39.4 % der Lohnunterschiede innerhalb der Firmen lassen sich durch Unterschiede in der Länge der Arbeitserfahrung zwischen den Mitarbeitenden einer Firma erklären (insgesamt, d.h. im Schnitt über alle Firmen).
\(~\)
Code
$random.intercept.preds <- predict(random.intercept.model)
df
ggplot(data = df, aes(
x = exp_centered,
y = random.intercept.preds,
colour = company
+
)) geom_smooth(method = "lm", fullrange = TRUE, se = F, size = .3) +
geom_jitter(aes(y = salary), alpha = .2) +
labs(x = xlabel, y = ylabel) +
ggtitle("Random-Intercept-Modell") +
geom_abline(
intercept = fixef(random.intercept.model)["(Intercept)"],
slope = fixef(random.intercept.model)["exp_centered"]
+
) scale_colour_discrete() +
::theme_tufte() ggthemes
1.5 Random-Coefficients-Modell (Modell 3)
Dieses Modell enthält sowohl einen Random-Intercept, als auch einen Random-Slope. Mit Hilfe dieses Modells kann die Varianz des Level-1-Slopes geschätzt werden. Damit erhalten wir ein Mass für die Unterschiedlichkeit des Effekts (Slope) des Level-1-Prädiktors (X, exp_centered
) auf die AV (Y, salary
) zwischen den Level-2-Einheiten (company)
.
Level-1-Modell:
\(\boldsymbol {y_{mi}=\beta_{0i} + \beta_{1i} \cdot x_{mi} + \varepsilon_{mi}}\)
Level-2-Modell:
\(\boldsymbol {\beta_{0i}=\gamma_{00} + \upsilon_{0i}}\)
\(\boldsymbol {\beta_{1i}=\gamma_{10} + \upsilon_{1i}}\)
Gesamtmodell:
\(\boldsymbol {y_{mi}=\gamma_{00} + \gamma_{10} \cdot x_{mi} + \upsilon_{0i} + \upsilon_{1i} \cdot x_{mi} + \varepsilon_{mi}}\)
1.5.1 Modell berechnen
# Fitten und Abspeichern des Modells.
# Wenn für eine Prädiktorvariable ein Random-Slope im Modell ist, muss der
# Intercept (also 1) nicht mehr zusätzlich im Klammerausdruck für die zufälligen
# Effekte angegeben werden.
<- lmer(salary ~ exp_centered + (exp_centered | company),
random.coefficients.model data = df, REML = TRUE
)
# Abspeichern von Prädiktionen, die dieses Modell macht.
# Wir speichern diese Prädiktionen, um das Modell später mit ggplot2
# zu veranschaulichen.
$random.coefficients.preds <- predict(random.coefficients.model)
df
# Output anschauen
summary(random.coefficients.model)
Linear mixed model fit by REML. t-tests use Satterthwaite's method [
lmerModLmerTest]
Formula: salary ~ exp_centered + (exp_centered | company)
Data: df
REML criterion at convergence: 1857.5
Scaled residuals:
Min 1Q Median 3Q Max
-2.8740 -0.6582 -0.0030 0.5957 3.3642
Random effects:
Groups Name Variance Std.Dev. Corr
company (Intercept) 0.8785 0.9373
exp_centered 0.0184 0.1357 0.71
Residual 1.1366 1.0661
Number of obs: 600, groups: company, 20
Fixed effects:
Estimate Std. Error df t value Pr(>|t|)
(Intercept) 8.73760 0.21405 19.00180 40.82 < 2e-16 ***
exp_centered 0.53050 0.04065 19.29006 13.05 5.03e-11 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Correlation of Fixed Effects:
(Intr)
exp_centerd 0.517
Die Ergebnisse zeigen, dass der Fixed-Effect von exp_centered
wiederum positiv signifikant ist \((\hat\gamma_{10} = 0.531, p < 0.001)\) (leicht unterschiedlich im Vergleich zum Random-Intercept-Modell). Das Hauptinteresse im Random-Coefficients-Modell gilt aber der Varianz bzw. Standardabweichung des Random-Slope: \(\hat\sigma^2_{\upsilon_1} = 0.0184\) und damit \(\hat\sigma_{\upsilon_1} = \sqrt{0.0184} = 0.1357\). Die durchschnittliche Abweichung (Level-2-Residuum \(\upsilon_{1i}\)) des exp_centered
-Effekts einer Firma vom mittleren Effekt \(\hat\gamma_{10}\) beträgt also 0.1357 Einheiten (135.7 CHF).
Mit der Funktion ranef()
kann man sich wieder die einzelnen Random-Effects (jetzt Level-2-Residuen des Intercepts \(\upsilon_{0i}\) und des Slopes \(\upsilon_{1i}\)) ausgeben lassen:
ranef(random.coefficients.model)
$company
(Intercept) exp_centered
Company 01 0.86293890 0.206681883
Company 02 1.15821543 0.162568896
Company 03 1.97985927 0.191185325
Company 04 -1.16452562 -0.098713123
Company 05 0.98756095 0.109771623
Company 06 -1.01080913 -0.155736947
Company 07 -0.01614998 -0.015646020
Company 08 -0.23431245 0.046670787
Company 09 -0.63383725 0.029503045
Company 10 0.79781128 0.093373856
Company 11 -0.49876825 0.007304942
Company 12 0.93628430 0.011592283
Company 13 -0.75506236 -0.048869511
Company 14 -1.01724817 -0.130249033
Company 15 -1.21946175 -0.176459297
Company 16 -0.14051872 -0.112235961
Company 17 0.66501590 0.023447960
Company 18 -0.20183736 -0.090510082
Company 19 0.35133550 0.008528235
Company 20 -0.84649052 -0.062208861
with conditional variances for "company"
Im Output befindet sich auch eine Angabe zum dritten Random-Effects-Parameter, der in diesem Modell geschätzt wurde, nämlich zur Kovarianz \(\hat\sigma_{\upsilon_0\upsilon_1}\) zwischen den Level-2-Residuen des Intercepts und den Level-2-Residuen des Slopes. Allerdings wird nicht die Kovarianz selbst ausgegeben, sondern ihre standardisierte Variante, die Korrelation \(r_{\upsilon_0\upsilon_1} = 0.71\). Diese besagt, dass der durchschnittliche Lohn eines Mitarbeitenden mit durchschnittlicher Erfahrung in einer Firma (vorhergesagter Wert von salary
an der Stelle exp_centered = 0)
positiv mit der Steigung von exp_centered
korreliert ist. Ein höherer Lohn für durchschnittlich erfahrene Mitarbeitende in einer Firma scheint also mit einem stärkeren Effekt von Erfahrung auf den Lohn in dieser Firma einherzugehen.
1.5.2 Signifikanztest für \(\sigma^2_{\upsilon_1}\): Modellvergleich mit Random-Intercept-Modell
Wenn wir dieses Modell mittels LR-Test mit dem Random-Intercept-Modell (s.o.) vergleichen, werden zwei Parameter gleichzeitig getestet: die Level-2-Varianz des Slopes (\(\sigma^2_{\upsilon_1}\)) und die Level-2-Kovarianz zwischen Intercept und Slope (\(\sigma_{\upsilon_0\upsilon_1}\)). Laut gegenwärtigem Forschungsstand ist dies die beste Methode, um zu überprüfen, ob es eine signifikante Slope-Varianz gibt (vgl. Eid et al., 2017).
1.5.2.1 Modellvergleich von Hand
Zunächst benötigen wir die -2-Log-Likelihoods (Devianzen) der beiden zu vergleichenden Modelle. Diese wird im Modelloutput des jeweiligen Modells unter der Bezeichnung “REML criterion at convergence” ausgegeben.
Wir folgen hier ausserdem den Bezeichnungen für uneingeschränkte Modelle \((M_u)\) und für eingeschränkte (restringierte) Modelle \((M_e)\), wie wir sie auch für die Modellvergleiche bei der logistischen Regression in Statistik III verwendet haben. \(M_u\) steht hier für das Random-Coefficients-Modell, das die zu testenden Parameter (Slope-Varianz \(\sigma^2_{\upsilon_1}\) und Intercept-Slope-Kovarianz \(\sigma_{\upsilon_0\upsilon_1}\)) enthält, \(M_e\) für das Random-Intercept-Model, das genau diese Parameter nicht enthält.
-2-Log-Likelihood random.intercept.model
(\(M_e\)): \(-2\cdot ln(L_e) = 1871.8\)
-2-Log-Likelihood random.coefficients.model
(\(M_u\)): \(-2\cdot ln(L_u) = 1857.5\)
Berechnen des Modellvergleichstests \(LR(M_u - M_e)\)
\(\chi^2_{emp} = [-2 \cdot ln(L_e)] - [-2 \cdot ln(L_u)] = 1871.8 - 1857.5 = 14.3\)
Anzahl Parameter \((nPar) \space M_u: \space \textbf{6} \space \space (\gamma_{00},\space\gamma_{10},\space\sigma^2_{\varepsilon}, \space\sigma^2_{\upsilon_0}, \space\sigma^2_{\upsilon_1}, \space\sigma_{\upsilon_0\upsilon_1})\)
Anzahl Parameter \((nPar) \space M_e:\space \textbf{4} \space \space (\gamma_{00}, \space\gamma_{10}, \space\sigma^2_{\varepsilon}, \space\sigma^2_{\upsilon_0})\)
\(LR(M_u - M_e)\) ist \(\chi^2\)-verteilt mit \(df = nPar(M_u) - nPar(M_e) = 6 - 4 = 2\)
Kritischer Wert: \(\chi^2_{(0.95, df = 2)} = 5.9915\)
\(~\)
Aber: Es handelt sich genau genommen um eine Mischverteilung aus \(\chi^2_{df=1}\) und \(\chi^2_{df=2}\), da einer der beiden getesteten Parameter \((\sigma^2_{\upsilon_1})\) einen bounded parameter space aufweist (kann nicht kleiner als 0 werden). Daher ist der korrekte kritische Chi-Quadrat-Wert hier das 95 %-Quantil dieser Mischverteilung und liegt bei (gerundet) 5.14 (vgl. Eid et al., 2017).
Der Test ist signifikant, da \(\chi^2_{emp} \space(=14.3) > \chi^2_{krit} \space(=5.14)\).
Beide Parameter zusammen unterscheiden sich also signifikant von 0. Der Fokus der Interpretation liegt hier aber auf dem Parameter der Slope-Varianz \(\sigma^2_{\upsilon_1}\) (nur wenn dieser > 0 ist, kann auch die Intercept-Slope-Kovarianz \(\sigma_{\upsilon_0\upsilon_1}\) überhaupt ungleich 0 sein).
Inhaltlich bedeutet dies, dass sich die Stärke des Effekts von exp_centered
auf salary
signifikant zwischen den Firmen (company
) unterscheidet. Die oben im Random-Coefficients-Modell geschätzte Slope-Varianz von exp_centered
\((\hat \sigma^2_{\upsilon_1} = 0.0184)\) ist damit als signifikant zu bewerten.
1.5.2.2 Modellvergleich in R
Wie beim Signifikanztest der Random-Intercept-Varianz \(\sigma^2_{\upsilon_0}\) im Intercept-Only-Modell können wir den Modellvergleich hier wieder mit ranova()
vornehmen. Wie oben wird ranova()
auf das uneingeschränkte Modell angewandt, die Angabe eines (eingeschränkten) Vergleichsmodells ist nicht notwendig.
ranova(random.coefficients.model)
ANOVA-like table for random-effects: Single term deletions
Model:
salary ~ exp_centered + (exp_centered | company)
npar logLik AIC LRT Df
<none> 6 -928.75 1869.5
exp_centered in (exp_centered | company) 4 -935.91 1879.8 14.316 2
Pr(>Chisq)
<none>
exp_centered in (exp_centered | company) 0.0007788 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
\(~\)
Alternativ können wir den Modellvergleich auch mit der uns bereits bekannten Funktion anova()
durchführen, indem wir die beiden zu vergleichenden Modelle explizit angeben:
anova(random.coefficients.model, random.intercept.model, refit = FALSE)
Data: df
Models:
random.intercept.model: salary ~ exp_centered + (1 | company)
random.coefficients.model: salary ~ exp_centered + (exp_centered | company)
npar AIC BIC logLik deviance Chisq Df
random.intercept.model 4 1879.8 1897.4 -935.91 1871.8
random.coefficients.model 6 1869.5 1895.9 -928.75 1857.5 14.316 2
Pr(>Chisq)
random.intercept.model
random.coefficients.model 0.0007788 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Das Ergebnis zeigt einen signifikanten LR-Test mit \(\chi^2_{emp} = 14.316\). Der (Rundungs-)Unterschied zum Modellvergleich von Hand ergibt sich wegen der ungenaueren Angabe der Devianzen in den Modelloutputs.
Der angegebene \(p\)-Wert ist allerdings noch nicht ganz korrekt, da einer der beiden Parameter - \(\sigma^2_{\upsilon_1}\) - wie oben bereits festgestellt einen bounded parameter space aufweist. Der korrekte \(p\)-Wert auf Basis der Mischverteilung ist daher noch etwas kleiner als der ausgegebene.
\(~\)
Code
# sal.visualisation$random.intercept.random.slope.plot
$random.coefficients.preds <- predict(random.coefficients.model)
df
ggplot(data = df, aes(x = exp_centered, y = random.coefficients.preds, colour = company)) +
geom_smooth(method = "lm", fullrange = TRUE, se = F, size = .3) +
labs(x = xlabel, y = ylabel) +
geom_jitter(aes(y = salary), alpha = .2) +
geom_abline(
intercept = fixef(random.coefficients.model)["(Intercept)"],
slope = fixef(random.coefficients.model)["exp_centered"]
+
) ggtitle("Random Coefficients Model") +
scale_colour_discrete() +
::theme_tufte() ggthemes