5  Kapitel 5: Hypothestentests 2 - Moderation und Mediation

if (!require("pacman")) install.packages("pacman")
Lade nötiges Paket: pacman
pacman::p_load(lmerTest, haven, brms, psych,
               sjmisc, sjlabelled, sjPlot, writexl, broom.mixed, qgraph,
               multilevelmediation,
               tidyverse, multilevelTools, parameters, devtools, reghelper
               )
load("../data/df_example1c.RData")

5.1 Cross-Level Interaktion / Moderation

Erwarten wir, dass der Effekt von täglichen Schwankungen in X auf Y abhängig von einer Variable ist, die auf Level-2 gemessen wird (z.B. relativ stabile Persönlichkeitsmerkmale), können wir dies mit einer Cross-Level Interaktion testen.

head(df_example1c)
id w y m x y_dm m_dm x_dm y_gm m_gm x_gm
1 3.847053 4.064028 8.492899 4.136489 -1.1414789 1.4106789 0.803986 5.205507 7.08222 3.332503
1 3.847053 3.599397 9.073630 3.728720 -1.6061099 1.9914099 0.396217 5.205507 7.08222 3.332503
1 3.847053 7.704277 4.082619 2.638451 2.4987701 -2.9996011 -0.694052 5.205507 7.08222 3.332503
1 3.847053 6.796018 5.516980 2.761167 1.5905111 -1.5652401 -0.571336 5.205507 7.08222 3.332503
1 3.847053 4.723777 6.875090 3.152261 -0.4817299 -0.2071301 -0.180242 5.205507 7.08222 3.332503
1 3.847053 3.592594 9.817786 4.168687 -1.6129129 2.7355659 0.836184 5.205507 7.08222 3.332503

Wir zentrieren den Moderator “w” auf dem Grand mean (Gesamtmittelwert) für eine einfachere Interpretation der Modellparameter.

df_example1c <- df_example1c |> center(w)
head(df_example1c)
id w y m x y_dm m_dm x_dm y_gm m_gm x_gm w_c
1 3.847053 4.064028 8.492899 4.136489 -1.1414789 1.4106789 0.803986 5.205507 7.08222 3.332503 0.81076
1 3.847053 3.599397 9.073630 3.728720 -1.6061099 1.9914099 0.396217 5.205507 7.08222 3.332503 0.81076
1 3.847053 7.704277 4.082619 2.638451 2.4987701 -2.9996011 -0.694052 5.205507 7.08222 3.332503 0.81076
1 3.847053 6.796018 5.516980 2.761167 1.5905111 -1.5652401 -0.571336 5.205507 7.08222 3.332503 0.81076
1 3.847053 4.723777 6.875090 3.152261 -0.4817299 -0.2071301 -0.180242 5.205507 7.08222 3.332503 0.81076
1 3.847053 3.592594 9.817786 4.168687 -1.6129129 2.7355659 0.836184 5.205507 7.08222 3.332503 0.81076

Die zentrierte Variable heisst “w_c” und wurde am Ende des Datensatz angehängt.

Zunächst berechnen wir das Modell ohne Interaktion von X und W (X*W), aber mit dem Haupteffekt von X und W.

Level 1: \(y_{ij} = \beta_{0j} + \beta_{1j}*(X_{ij}-\bar{X_j}) + \beta_{2j}*W_{j} + e_{ij}\)

Level 2 (random intercept): \(\beta_{0j} = \gamma_{00} + u_{0j}\)

Level 2 (random slope for x): \(\beta_{1j} = \gamma_{10} + u_{2j}\)

ri.rs_w_modell <- lmer(y ~ x_dm + w_c + (1 + x_dm | id), data = df_example1c)
model_parameters(ri.rs_w_modell) |> print_html()
Model Summary
Parameter Coefficient SE 95% CI t(993) p
Fixed Effects
(Intercept) 5.52 0.10 (5.33, 5.70) 57.83 < .001
x dm 1.20 0.11 (0.98, 1.42) 10.68 < .001
w c 0.44 0.15 (0.14, 0.74) 2.91 0.004
Random Effects
SD (Intercept: id) 0.93
SD (x_dm: id) 1.07
Cor (Intercept~x_dm: id) 0.15
SD (Residual) 0.66

Der Moderator W hat einen positiven Haupteffekt auf die abhängige Variable.

Als nächstes fügen wir den Interaktionsterm hinzu.

Level 1: \(y_{ij} = \beta_{0j} + \beta_{1j}\cdot(X_{ij}-\bar{X_j}) + \beta_{2j}\cdot W_{j} + e_{ij}\)

Level 2 (random intercept): \(\beta_{0j} = \gamma_{00} + u_{0j}\)

Level 2 (random slope for x): \(\beta_{1j} = \gamma_{10} + \gamma_{11}*W_{j} + u_{2j}\)

ri.rs_cli_modell <- lmer(y ~ x_dm + w_c + w_c*x_dm + (1 + x_dm | id), data = df_example1c)
model_parameters(ri.rs_cli_modell) |> print_html()
Model Summary
Parameter Coefficient SE 95% CI t(992) p
Fixed Effects
(Intercept) 5.52 0.10 (5.33, 5.70) 57.85 < .001
x dm 1.20 0.11 (0.98, 1.41) 10.89 < .001
w c 0.49 0.15 (0.19, 0.79) 3.19 0.001
x dm × w c 0.39 0.18 (0.05, 0.74) 2.23 0.026
Random Effects
SD (Intercept: id) 0.93
SD (x_dm: id) 1.04
Cor (Intercept~x_dm: id) 0.14
SD (Residual) 0.66

Beachtet, dass mit der eingebauten Interaktion die Haupteffekte nicht mehr interpretiert werden.

5.1.1 Visualisierung

Visualisierung des Interaktionseffekt mittels der plot_model() Funktion. Standardmässig werden die Simple Slopes an den Extremwerten (Minimum, Maximum) des Moderators geschätzt.

Die Simple-Slope-Analyse in Mehrebenen-Modellen dient dazu, den Moderationseffekt einer Variablen zu untersuchen, indem die Beziehung zwischen Prädiktor (hier: “x”) und abhängiger Variable (hier: “y”) auf verschiedenen Ausprägungsniveaus der Moderatorvariablen (hier: “w_c”) betrachtet wird. Nach der Schätzung des Mehrebenen-Modells werden die Steigungen (Slopes) für unterschiedliche Werte des Moderators berechnet (z. B. ±1 Standardabweichung oder spezifische Werte), um zu analysieren, ob und wie sich der Effekt des Prädiktors je nach Moderator ändert. Diese Methode hilft zu verstehen, ob die Stärke oder Richtung eines Effekts in Abhängigkeit der Moderatorvariable variiert.

plot_model(ri.rs_cli_modell,
           type = "int", # typ interaktion
           terms = c("x_dm", "w_c")) # die terme (variablen) aus denen die Interaktion gebildet wird

Alternativ kann man auch die Werte zum Mittelwerte und bei -1 SD und +1 SD des Moderators anzeigen lassen. Wir können den zuletzt erzeugten Plot mittels ggsave() abspeichern.

plot_model(ri.rs_cli_modell, type = "int", mdrt.values = "meansd")

ggsave("Plots/CLI_Beispiel.png")
Saving 7 x 5 in image

Der Plot zeigt, dass bei höheren Ausprägungen von w der Effekt von x_dm stärker ausfällt.

5.1.2 Simple Slopes Analyse

Mit Hilfe der simple_slopes() Funktion aus dem reghelper Paket können wir uns die Regressionskoeffizienten einer Simple-Slope Analyse unterziehen. Die statistischen Kennwerte dienen als Zusatz zur Visualisierung der Simple Slopes. So können wir z.B. bestimmen, ob der Effekt von X auf Y auf verschiedenen Ausprägungen signifikant ist. Z.B. könnte der Effekt von X auf Y nur bei bestimmten Ausprägungen (hoch oder niedrig) signifikant sein.

Wir können die spezifischen Werte der Variable automatisch bestimmen (1. Variante) oder manuell setzen (2. Variante). Uns interessieren die Werte, wenn x_dm um eine Einheit steigt und der Moderator unterdurchschnittlich (-1 SD), durchschnittlich, oder überdurchschnittlich (+1 SD) ist. Entsprechend werden die Werte in Variante 2 manuell gesetzt. Die Werte können wir der Abbildung oben entnehmen.

simple_slopes(ri.rs_cli_modell)
x_dm w_c Test Estimate Std. Error df t value Pr(>|t|)
-0.663149 sstest 0.2286100 0.1800277 96.65133 1.269861 0.2071831
0 sstest 0.4892460 0.1535760 97.99976 3.185694 0.0019372
0.663149 sstest 0.7498820 0.2048973 97.16437 3.659794 0.0004104
sstest -0.621309 0.9540629 0.1553862 95.45208 6.139946 0.0000000
sstest 0 1.1982546 0.1099985 95.83814 10.893368 0.0000000
sstest 0.621309 1.4424463 0.1547564 94.09284 9.320752 0.0000000
simple_slopes(ri.rs_cli_modell,
              levels = list(x_dm = c(1,'sstest') ),
              w_c = c(-0.62,0, 0.62, "sstest"))
x_dm w_c Test Estimate Std. Error df t value Pr(>|t|)
1 sstest 0.8822738 0.2485026 96.49868 3.550360 0.0005966
sstest -0.621309 0.9540629 0.1553862 95.45208 6.139946 0.0000000
sstest 0 1.1982546 0.1099985 95.83814 10.893368 0.0000000
sstest 0.621309 1.4424463 0.1547564 94.09284 9.320752 0.0000000

Die Simple Slope Analyse bestätigt die Visualiserung und zeigt, dass der Effekt von x_dm auf y schwächer ausfällt, aber immer noch signifikant positiv ist, wenn der Moderator w_c unterdurchschnittlich ist (Variante 1, Zeile 4; Variante 2, Zeile 2). Der Effekt fällt stärker aus, wenn der Moderator w_c überdurchschnittlich ist (Variante 1, Zeile 6; Variante 2, Zeile 4).

5.1.3 Within-level Interaktion

Analog zur Cross-level Interaktion gibt es auch Within-level Interaktionen, bei der die Level-1 Anteile von Prädiktorvariablen miteinander interagieren.

Level 1: \(y_{ij} = \beta_{0j} + \beta_{1j}\cdot(X_{ij}-\bar{X_j}) + \beta_{2j}\cdot(W_{ij}-\bar{W_j}) + \beta_{3j}\cdot((W_{ij}-\bar{W_j})\cdot(X_{ij}-\bar{X_j})) + e_{ij}\)

Level 2 (random intercept): \(\beta_{0j} = \gamma_{00} + u_{0j}\)

Level 2 (random slope X): \(\beta_{1j} = \gamma_{10} + u_{1j}\)

Level 2 (random slope M): \(\beta_{2j} = \gamma_{20} + u_{2j}\)

ri.rs_wli_modell <- lmer(y ~ x_dm + m_dm + x_dm*m_dm + (1 + x_dm + m_dm | id), data = df_example1c)
model_parameters(ri.rs_wli_modell) |> print_html()
Model Summary
Parameter Coefficient SE 95% CI t(989) p
Fixed Effects
(Intercept) 5.52 0.10 (5.32, 5.72) 54.89 < .001
x dm 0.17 0.08 (9.53e-03, 0.33) 2.08 0.038
m dm 0.53 0.06 (0.41, 0.66) 8.46 < .001
x dm × m dm -5.19e-03 0.02 (-0.04, 0.02) -0.34 0.735
Random Effects
SD (Intercept: id) 0.98
SD (x_dm: id) 0.47
SD (m_dm: id) 0.53
Cor (Intercept~x_dm: id) -0.08
Cor (Intercept~m_dm: id) 0.04
Cor (x_dm~m_dm: id) -0.26
SD (Residual) 0.52
plot_model(ri.rs_wli_modell, type = "int", mdrt.values = "meansd")

Der Interaktionseffekt ist nicht signifikant. Dies bedeutet, wie der Plot zeigt, dass die Linien bei allen Ausprägungen des Moderators mehr oder wenig parallel sind.

5.2 Übung

Wir arbeiten in der Übung mit dem Übungs-Datensatz aus Kapitel 4.

load("../data/df_example_cli.RData")

head(df_example_cli)
id illtask negativ support illtask_dm negativ_dm illtask_gm negativ_gm negativ_dm_l1 day
1 1.188858 1.825857 3.454777 -1.2994333 -0.0153842 2.488291 1.841241 NA 1
1 1.719163 1.633681 3.454777 -0.7691283 -0.2075602 2.488291 1.841241 NA 4
1 3.149280 1.250429 3.454777 0.6609887 -0.5908122 2.488291 1.841241 NA 7
1 2.372508 1.583838 3.454777 -0.1157833 -0.2574032 2.488291 1.841241 -0.5908122 8
1 2.558448 2.912401 3.454777 0.0701567 1.0711598 2.488291 1.841241 -0.2574032 9
2 1.336438 2.111289 2.109855 0.2807496 -0.4911521 1.055688 2.602441 NA 1
get_label(df_example_cli)
                                         id 
                              "Personen-ID" 
                                    illtask 
                 "Daily Illegitimate Tasks" 
                                    negativ 
                    "Daily Negative Affect" 
                                    support 
                         "Coworker support" 
                                 illtask_dm 
"Illegitimate Tasks (person-mean centered)" 
                                 negativ_dm 
       "Neg. Affect (person-mean centered)" 
                                 illtask_gm 
      "Illegitimate Tasks (person average)" 
                                 negativ_gm 
             "Neg. Affect (person average)" 
                              negativ_dm_l1 
                 "Previous-day Neg. Affect" 
                                        day 
                               "Tag (1-10)" 
# alternativ
view_df(df_example_cli)
Data frame: df_example_cli
ID Name Label Values Value Labels
1 id Personen-ID range: 1-100
2 illtask Daily Illegitimate Tasks range: -1.9-5.6
3 negativ Daily Negative Affect range: -0.2-7.7
4 support Coworker support range: 1.4-4.5
5 illtask_dm Illegitimate Tasks (person-mean centered) range: -2.1-2.3
6 negativ_dm Neg. Affect (person-mean centered) range: -2.0-2.7
7 illtask_gm Illegitimate Tasks (person average) range: -0.7-4.7
8 negativ_gm Neg. Affect (person average) range: 0.8-5.0
9 negativ_dm_l1 Previous-day Neg. Affect range: -2.0-2.7
10 day Tag (1-10) range: 1-10

Berechne Modelle mit denen du die folgenden Hypothesen testest:

H1: Illegitime Aufgaben hängen positiv mit negativem Affekt zusammen. H2: Der positive Zusammenhang von illegitime Aufgaben mit negativem Affekt fällt schwächer aus, wenn Unterstützung von Kolleg:innen hoch ausgeprägt ist.

Gehe Schritt für Schritt vor und teste erst in einem Modell H1 (verwende dazu den Random Intercept, Random Slope Modell-Code aus dem letzten Kapitel), dann in einem anderen Modell H2. Urteile, ob die Hypothesen angenommen oder verworfen werden sollten.

ri.rs_modell <- lmer(negativ ~ illtask_dm  + support + (1 + illtask_dm | id), data = df_example_cli)
parameters(ri.rs_modell)
Parameter Coefficient SE CI CI_low CI_high t df_error p Effects Group
(Intercept) 3.4515583 0.3038234 0.95 2.8551451 4.0479715 11.360409 776 0.0000000 fixed
illtask_dm 0.3256395 0.0513930 0.95 0.2247537 0.4265253 6.336261 776 0.0000000 fixed
support -0.2468958 0.1012860 0.95 -0.4457228 -0.0480687 -2.437610 776 0.0150083 fixed
SD (Intercept) 0.6661075 NA 0.95 NA NA NA NA NA random id
SD (illtask_dm) 0.3534636 NA 0.95 NA NA NA NA NA random id
Cor (Intercept~illtask_dm) 0.6940618 NA 0.95 NA NA NA NA NA random id
SD (Observations) 0.6775572 NA 0.95 NA NA NA NA NA random Residual

Der Zusammenhang von täglichen illegitimen Aufgaben (illtask_dm) mit negativem Affekt (negativ) ist signifikant (b = 0.33, p < .001), was Hypothese 1 unterstützt.

ri.rs_cli_modell <- lmer(negativ ~ illtask_dm  + support*illtask_dm + (1 + illtask_dm | id), data = df_example_cli)
parameters(ri.rs_cli_modell)
Parameter Coefficient SE CI CI_low CI_high t df_error p Effects Group
(Intercept) 3.4723696 0.3361052 0.95 2.8125852 4.1321541 10.3311992 775 0.0000000 fixed
illtask_dm 0.3598764 0.2459646 0.95 -0.1229594 0.8427122 1.4631228 775 0.1438392 fixed
support -0.2540133 0.1126112 0.95 -0.4750724 -0.0329541 -2.2556656 775 0.0243697 fixed
illtask_dm:support -0.0116576 0.0823355 0.95 -0.1732847 0.1499694 -0.1415871 775 0.8874429 fixed
SD (Intercept) 0.6668935 NA 0.95 NA NA NA NA NA random id
SD (illtask_dm) 0.3567497 NA 0.95 NA NA NA NA NA random id
Cor (Intercept~illtask_dm) 0.6950819 NA 0.95 NA NA NA NA NA random id
SD (Observations) 0.6776777 NA 0.95 NA NA NA NA NA random Residual

Der Interaktionseffekt von täglichen illegitimen Aufgaben mit sozialer Unterstützung durch Kolleg:innen auf negativen Affekt ist nicht signifikant (b = -0.01, p = .89). Hypothese 2 muss somit verworfen werden.

5.3 1-1-1 Mediation

Die 1-1-1 Mediation ist die gängigste Variante, in der alle Variablen (X, M[ediator], und Y) auf Tagesebene gemessen werden.

5.3.1 Daten einlesen

load("../data/df_example1.RData")
head(df_example1)
id y m x y_dm m_dm x_dm y_gm m_gm x_gm
1 4.003538 4.769391 2.365486 -0.3020232 0.8945291 0.6845636 4.305561 3.874862 1.680922
1 4.925174 2.510943 0.748855 0.6196128 -1.3639189 -0.9320674 4.305561 3.874862 1.680922
1 4.598564 3.098112 1.395041 0.2930028 -0.7767499 -0.2858814 4.305561 3.874862 1.680922
1 4.286179 4.610746 1.860026 -0.0193822 0.7358841 0.1791036 4.305561 3.874862 1.680922
1 4.183494 4.549044 2.288019 -0.1220672 0.6741821 0.6070966 4.305561 3.874862 1.680922
1 3.631716 3.590049 1.696510 -0.6738452 -0.2848129 0.0155876 4.305561 3.874862 1.680922

Zum Testen des Mediationsmodells verwenden wir zunächst die Funktion modmed.mlm(). Im Folgenden erstellen wir mit dieser Funktion ein Mediationsmodell und spezifizieren bei den Argumenten X, Y, und M die die unabhängige, abhängige, und mediierende Variable. Für die abhängige Variable Y wählen wir die Rohvariable, für unabhängige und mediierende Variablen die personen-zentrierten Variablen.

Anders als bei den früheren Analysen steht uns das parameters Paket hier nicht zur Verfügung um die Ergebnisse zusammenzufassen. Stattdessen nehmen wir die summary() Funktion oder die tidy()-Funktion aus dem broom Paket.

fit_mediation <- modmed.mlm(
  df_example1,
  L2ID = "id",
  X = "x_dm",
  Y = "y",
  M = "m_dm",
  random.int.m = FALSE,
  na.action = na.omit
)

#summary(fit_mediation$model)
broom::tidy(fit_mediation$model) |>
  mutate(across(where(is.numeric), round, 2)) # rundung der werte
Warning: There was 1 warning in `mutate()`.
ℹ In argument: `across(where(is.numeric), round, 2)`.
Caused by warning:
! The `...` argument of `across()` is deprecated as of dplyr 1.1.0.
Supply arguments directly to `.fns` through an anonymous function instead.

  # Previously
  across(a:b, mean, na.rm = TRUE)

  # Now
  across(a:b, \(x) mean(x, na.rm = TRUE))
effect group term estimate std.error df statistic p.value
fixed NA Sm 0.00 0.02 1896 0.00 1
fixed NA Sy 5.37 0.09 1896 61.50 0
fixed NA SmX 0.51 0.03 1896 17.81 0
fixed NA SyX 0.14 0.04 1896 3.63 0
fixed NA SyM 0.58 0.04 1896 15.96 0
ran_pars L2id sd_Sy 0.84 NA NA NA NA
ran_pars Residual sd_Observation 0.70 NA NA NA NA
var_model varIdent(1 | Sm) 0 1.00 NA NA NA NA
var_model varIdent(1 | Sm) 1 0.87 NA NA NA NA

Die ausgegebenen Zeilen/Parameter sind etwas kryptisch beschrieben.

  • Sm - fixed Intercept von M
  • Sy - fixed Intercept von Y
  • SmX - fixed Slope von X auf M (a-Pfad)
  • SyX - fixed Slope von Y auf X (c’-Pfad)
  • SyM - fixed Slope von Y auf M (b-Pfad)

5.3.2 Bootstrapped Version

Der indirekte Effekt von X auf Y via M (a-Pfad * b-Pfad) der uns in der Mediation von zentralem Interesse ist, ist in der Regel nicht normalverteilt, da ein Produkt zweier (oder mehrerer) Pfadkoeffizienten nicht wie die Pfadkoeffizienten selber approximativ normalverteilt ist. Aufgrund der fehlenden Normalverteilung verwenden wir die Bootstrap-Schätzung, um eine robustere Aussage über die Signifikanz des indirekten Effekts zu bekommen.

boot.custom.results <- boot.modmed.mlm.custom(
  data = df_example1 |> as.data.frame(),
  L2ID = "id",
  X = "x_dm",
  Y = "y",
  M = "m_dm",
  random.int.m = FALSE,
  control = list(opt = "nlm"),
  na.action = na.omit,
  return.type = "all",
  nrep = 1000,
  parallel.type = "parallel",
  ncores = 4,
  seed = 2299)
broom::tidy(boot.custom.results$model) |>
  mutate(across(where(is.numeric), round, 2)) # rundung der werte
effect group term estimate std.error df statistic p.value
fixed NA Sm 0.00 0.02 1896 0.00 1
fixed NA Sy 5.37 0.09 1896 61.50 0
fixed NA SmX 0.51 0.03 1896 17.81 0
fixed NA SyX 0.14 0.04 1896 3.63 0
fixed NA SyM 0.58 0.04 1896 15.96 0
ran_pars L2id sd_Sy 0.84 NA NA NA NA
ran_pars Residual sd_Observation 0.70 NA NA NA NA
var_model varIdent(1 | Sm) 0 1.00 NA NA NA NA
var_model varIdent(1 | Sm) 1 0.87 NA NA NA NA

Nach der Schätzung des Modells müssen wir das 95% Konfidenzintervall des indirekten Effekts aus den Modellergebnissen extrahieren. Dazu gibt es derzeit keine einfache Funktion, entsprechend fällt der folgende Code-Chunk komplexer aus.

# Punktwert des indirekten Effekt
indirect_punktschaetzung <- extract.modmed.mlm(boot.custom.results, type="indirect")

# Bootstrapped 95% Konfidenzintervall um den Punktwert herum
indirect_boot <- tibble(SyM = boot.custom.results[["t"]][,which(names(boot.custom.results[["t0"]]) == "SyM")], 
                        SmX = boot.custom.results[["t"]][,which(names(boot.custom.results[["t0"]]) == "SmX")]) |> 
  mutate(indirect = SyM * SmX)
indirekt_ci <- quantile(indirect_boot$indirect, c(0.025, 0.975), na.rm = TRUE)

# zusammenfassen
indirekt_zusammenfassung <-
  tibble(Koeffizient = indirect_punktschaetzung,
         LLCI = indirekt_ci[1],
         ULCI = indirekt_ci[2]) |> 
  mutate(across(where(is.numeric), round, 3))
indirekt_zusammenfassung
Koeffizient LLCI ULCI
0.3 0.198 0.411
  • LLCI = Lower Limit of Confidence Interval
  • ULCI = Upper Limit of Confidence Interval

Der indirekte Effekt und sein 95% Konfidenzintervall müssen wir aus den Daten extrahieren. Wenn der 95% Konfidenzintervall die 0 ausschliesst (also sowohl unterer als auch oberes Limit entweder unter Null oder über Null liegen) können wir den indirekten Effekt als signifikant ansehen.

In diesem Beispiel finden wir also einen signifikanten indirekten Effekt mit Koeffizient = 0.30, 95% CI = [0.19, 0.41].

5.4 Übung

Wir arbeiten in der Übung mit einem neuen Datensatz.

Mache dich mit ihm vertraut. Wie in der Cross-Level Interaktionsübung benutzen wir einen Datensatz in dem die Variablen “labelled” sind, also Beschriftungen haben. Wir können die Labels mit get_label() abrufen.

load("../data/df_111_uebung.RData")

head(df_111_uebung)
id helfen wertschaetz selbstwert wertschaetz_dm selbstwert_dm wertschaetz_gm selbstwert_gm
1 4.714438 1.371902 4.441296 -0.0437649 -0.7058638 1.415667 5.14716
1 3.622743 0.574266 5.981966 -0.8414009 0.8348062 1.415667 5.14716
1 5.337310 1.472314 5.407452 0.0566471 0.2602922 1.415667 5.14716
1 4.938451 2.790352 5.428928 1.3746851 0.2817682 1.415667 5.14716
1 3.742165 1.204333 5.369987 -0.2113339 0.2228272 1.415667 5.14716
1 4.607774 1.744993 4.644467 0.3293261 -0.5026928 1.415667 5.14716
get_label(df_111_uebung)
                                               id 
                                    "Personen-ID" 
                                           helfen 
                              "Proaktives Helfen" 
                                      wertschaetz 
                       "erfahrene Wertschaetzung" 
                                       selbstwert 
                                     "Selbstwert" 
                                   wertschaetz_dm 
"erfahrene Wertschaetzung (person-mean centered)" 
                                    selbstwert_dm 
              "Selbstwert (person-mean centered)" 
                                   wertschaetz_gm 
      "erfahrene Wertschaetzung (person average)" 
                                    selbstwert_gm 
                    "Selbstwert (person average)" 
# alternativ
view_df(df_111_uebung)
Data frame: df_111_uebung
ID Name Label Values Value Labels
1 id Personen-ID 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<... truncated>
2 helfen Proaktives Helfen range: 0.1-9.1
3 wertschaetz erfahrene Wertschaetzung range: -2.4-5.5
4 selbstwert Selbstwert range: 0.9-8.0
5 wertschaetz_dm erfahrene Wertschaetzung (person-mean centered) range: -2.0-2.4
6 selbstwert_dm Selbstwert (person-mean centered) range: -2.7-2.5
7 wertschaetz_gm erfahrene Wertschaetzung (person average) range: -1.0-4.6
8 selbstwert_gm Selbstwert (person average) range: 2.7-6.4

Berechne Modelle mit denen du die folgenden Hypothesen testest:

H1: Tägliche Wertschätzung durch Vorgesetzte und Kolleg:innen hängen positiv mit dem täglichen Selbstwert zusammen. H2: Täglicher Selbstwert hängt positiv mit täglichem proaktivem Helfen zusammen. H3: Es gibt einen positiven indirekten Zusammenhang zwischen täglicher Wertschätzung und täglichem proaktiven Helfen, vermittel durch den täglichen Selbstwert.

Teste die Hypothesen in einem Modell mittels der boot.modmed.mlm.custom() Funktion. Urteile, ob die Hypothesen angenommen oder verworfen werden sollten.

# | cache: true
boot.custom.results <- boot.modmed.mlm.custom(
  data = df_111_uebung |> remove_all_labels(),
  L2ID = "id",
  X = "wertschaetz_dm",
  Y = "helfen",
  M = "selbstwert_dm",
  random.int.m = FALSE,
  control = list(opt = "nlm"),
  na.action = na.omit,
  return.type = "all",
  nrep = 1000,
  parallel.type = "parallel",
  ncores = 4,
  seed = 2299)
broom::tidy(boot.custom.results$model) |>
  mutate(across(where(is.numeric), round, 2)) # rundung der werte
effect group term estimate std.error df statistic p.value
fixed NA Sm 0.00 0.02 1896 0.00 1
fixed NA Sy 4.76 0.10 1896 49.39 0
fixed NA SmX 0.40 0.03 1896 13.81 0
fixed NA SyX 0.33 0.04 1896 8.93 0
fixed NA SyM 0.14 0.04 1896 3.84 0
ran_pars L2id sd_Sy 0.94 NA NA NA NA
ran_pars Residual sd_Observation 0.74 NA NA NA NA
var_model varIdent(1 | Sm) 0 1.00 NA NA NA NA
var_model varIdent(1 | Sm) 1 0.85 NA NA NA NA
# Punktwert des indirekten Effekt
indirect_punktschaetzung <- extract.modmed.mlm(boot.custom.results, type="indirect")

# Bootstrapped 95% Konfidenzintervall um den Punktwert herum
indirect_boot <- tibble(SyM = boot.custom.results[["t"]][,which(names(boot.custom.results[["t0"]]) == "SyM")], 
                        SmX = boot.custom.results[["t"]][,which(names(boot.custom.results[["t0"]]) == "SmX")]) |> 
  mutate(indirect = SyM * SmX)
indirekt_ci <- quantile(indirect_boot$indirect, c(0.025, 0.975), na.rm = TRUE)

# zusammenfassen
indirekt_zusammenfassung <-
  tibble(Koeffizient = indirect_punktschaetzung,
         LLCI = indirekt_ci[1],
         ULCI = indirekt_ci[2]) |> 
  mutate(across(where(is.numeric), round, 3))
indirekt_zusammenfassung
Koeffizient LLCI ULCI
0.057 -0.005 0.138

H1 wird unterstützt (SmX: b = 0.40, p < .001). H2 wird verworfen (SyM: b = 0.14, p < .40). H3: wird entsprechend auch verworfen (95% CI des indirekten Effekt schliesst die 0 ein). Es besteht aber ein direkter Zusammenhang zwischen X und Y (SyX: b = 0.33, p < .001), der, anders als angenommen, nicht indirekt über Selbstwert vermittelt wird.