Two-level SEM with within-dyad gender interactions
The MLM moderator tutorial added gender × predictor interactions to a long-format multilevel model. This tutorial does the same thing in lavaan, using the two-level SEM specification that decomposes variance into within-dyad and between-dyad components.
The two specifications should give you nearly identical estimates for the within-dyad effects. The SEM version is more transparent about which interactions are at the within level and which covariates are at the between level.
Place the four within-dyad predictors at the within level and the two dyad-level covariates at the between level. The two-level SEM is the SEM analogue of the MLM tutorial.
Code
model_base<-' level: within satisfaction ~ a_w*wnc + p_w*partner_wnc + ar_w*recovery + pr_w*partner_recovery level: between satisfaction ~ c_child*has_children + c_dual*dual_earner'fit_base<-sem(model_base, data =ddl, cluster ="dyad_id")summary(fit_base, standardized =TRUE, fit.measures =TRUE)
lavaan 0.6-21 ended normally after 22 iterations
Estimator ML
Optimization method NLMINB
Number of model parameters 9
Number of observations 200
Number of clusters [dyad_id] 100
Model Test User Model:
Test statistic 0.000
Degrees of freedom 0
Model Test Baseline Model:
Test statistic 133.662
Degrees of freedom 6
P-value 0.000
User Model versus Baseline Model:
Comparative Fit Index (CFI) 1.000
Tucker-Lewis Index (TLI) 1.000
Loglikelihood and Information Criteria:
Loglikelihood user model (H0) -129.318
Loglikelihood unrestricted model (H1) -129.319
Akaike (AIC) 276.635
Bayesian (BIC) 306.320
Sample-size adjusted Bayesian (SABIC) 277.807
Root Mean Square Error of Approximation:
RMSEA 0.000
90 Percent confidence interval - lower 0.000
90 Percent confidence interval - upper 0.000
P-value H_0: RMSEA <= 0.050 NA
P-value H_0: RMSEA >= 0.080 NA
Standardized Root Mean Square Residual (corr metric):
SRMR (within covariance matrix) 0.000
SRMR (between covariance matrix) 0.003
Parameter Estimates:
Standard errors Standard
Information Observed
Observed information based on Hessian
Level 1 [within]:
Regressions:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
satisfaction ~
wnc (a_w) -0.256 0.040 -6.461 0.000 -0.256 -0.377
prtnr_w (p_w) -0.178 0.040 -4.491 0.000 -0.178 -0.262
recovry (ar_w) 0.226 0.038 5.956 0.000 0.226 0.309
prtnr_r (pr_w) 0.125 0.038 3.286 0.001 0.125 0.171
Variances:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
.satisfaction 0.188 0.027 7.071 0.000 0.188 0.409
Level 2 [dyad_id]:
Regressions:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
satisfaction ~
hs_chld (c_ch) 0.026 0.078 0.338 0.735 0.026 0.059
dul_rnr (c_dl) 0.305 0.078 3.928 0.000 0.305 0.647
Intercepts:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
.satisfaction 4.824 0.166 29.099 0.000 4.824 22.366
Variances:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
.satisfaction 0.027 0.022 1.246 0.213 0.027 0.581
Add gender × predictor interactions
The within-dyad level now includes the gender main effect and the gender × actor/partner WNC interactions. The between-dyad level is unchanged.
lavaan 0.6-21 ended normally after 25 iterations
Estimator ML
Optimization method NLMINB
Number of model parameters 12
Number of observations 200
Number of clusters [dyad_id] 100
Model Test User Model:
Test statistic 0.000
Degrees of freedom 0
Model Test Baseline Model:
Test statistic 154.210
Degrees of freedom 9
P-value 0.000
User Model versus Baseline Model:
Comparative Fit Index (CFI) 1.000
Tucker-Lewis Index (TLI) 1.000
Loglikelihood and Information Criteria:
Loglikelihood user model (H0) -119.044
Loglikelihood unrestricted model (H1) -119.045
Akaike (AIC) 262.089
Bayesian (BIC) 301.668
Sample-size adjusted Bayesian (SABIC) 263.651
Root Mean Square Error of Approximation:
RMSEA 0.000
90 Percent confidence interval - lower 0.000
90 Percent confidence interval - upper 0.000
P-value H_0: RMSEA <= 0.050 NA
P-value H_0: RMSEA >= 0.080 NA
Standardized Root Mean Square Residual (corr metric):
SRMR (within covariance matrix) 0.000
SRMR (between covariance matrix) 0.001
Parameter Estimates:
Standard errors Standard
Information Observed
Observed information based on Hessian
Level 1 [within]:
Regressions:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
satisfaction ~
wnc (a_w) -0.300 0.125 -2.397 0.017 -0.300 -0.449
prtnr_w (p_w) -0.020 0.130 -0.151 0.880 -0.020 -0.029
recovry (ar_w) 0.247 0.037 6.770 0.000 0.247 0.344
prtnr_r (pr_w) 0.109 0.037 2.979 0.003 0.109 0.151
gndr_nm (g_w) -0.262 0.058 -4.490 0.000 -0.262 -0.197
wnc_x_g (aw_n) 0.007 0.081 0.090 0.928 0.007 0.017
prtn___ (pw_n) -0.082 0.081 -1.009 0.313 -0.082 -0.200
Variances:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
.satisfaction 0.154 0.022 7.071 0.000 0.154 0.346
Level 2 [dyad_id]:
Regressions:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
satisfaction ~
hs_chld (c_ch) 0.032 0.078 0.408 0.683 0.032 0.061
dul_rnr (c_dl) 0.303 0.077 3.909 0.000 0.303 0.553
Intercepts:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
.satisfaction 5.206 0.188 27.673 0.000 5.206 20.725
Variances:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
.satisfaction 0.044 0.020 2.164 0.030 0.044 0.694
Defined Parameters:
Estimate Std.Err z-value P(>|z|) Std.lv Std.all
ss_wnc_M -0.292 0.054 -5.459 0.000 -0.292 -0.432
ss_wnc_F -0.285 0.057 -4.967 0.000 -0.285 -0.415
ss_pwnc_M -0.102 0.057 -1.770 0.077 -0.102 -0.229
ss_pwnc_F -0.184 0.054 -3.427 0.001 -0.184 -0.429
Reading the calculated simple slopes
The := operator in lavaan defines a user-calculated parameter. The simple slopes are functions of the base coefficient and the interaction coefficient, evaluated at the male and female values of gender_num.
The within-dyad SEM aw_int coefficient (gender × actor WNC) and pw_int (gender × partner WNC) should match the corresponding wnc:genderfemale and partner_wnc:genderfemale interactions in the MLM moderator tutorial. The simple slopes for males and females should also match the sim_slopes() output.
Why “model is saturated” matters here
The two-level SEM with the within-dyad interactions has just-identified within-level equations: the four predictors plus three interaction terms and a gender main effect consume all the within-dyad degrees of freedom. This means:
The chi-square test of model fit is exactly zero (or near it) by construction.
The standard chi-square difference test is not available for comparing the baseline and moderator models.
If you want a formal LRT, the right move is to fit both models in the wide format (see the SEM wide tutorial), or to use the MLM moderator approach, where the LRT is well-defined.
What to take away
Key takeaways
The two-level SEM makes the within/between decomposition of effects explicit.
Gender × predictor interactions live at the within-dyad level.
Dyad-level covariates (no within-dyad variance) live at the between-dyad level.
Calculated simple slopes via := give you the conditional effects at each level of the moderator.
The model is just-identified within-dyad, so the chi-square LRT is not available; use the MLM version for hypothesis testing.
What to read next
The SEM wide tutorial — wide format, the three-model sequence, the k-pattern tests.
The two-intercept tutorial — a parameterisation trick that estimates both intercepts directly.
---title: "Distinguishable dyads: SEM with moderation"subtitle: "Two-level SEM with within-dyad gender interactions"---The [MLM moderator tutorial](mlm-moderator.html) added gender ×predictor interactions to a long-format multilevel model. Thistutorial does the same thing in `lavaan`, using the two-level SEMspecification that decomposes variance into within-dyad andbetween-dyad components.The two specifications should give you nearly identical estimatesfor the within-dyad effects. The SEM version is more transparentabout which interactions are at the within level and whichcovariates are at the between level.## Setup```{r}#| label: setup#| message: false#| warning: falselibrary(lavaan)library(dplyr)load("../../../data/dyad_data.RData")# Numeric gender indicator for interactions# Male = 1, Female = 2 (matches R's default factor coding)ddl$gender_num <-as.numeric(ddl$gender)# Manual interaction columnsddl$wnc_x_gender <- ddl$wnc * ddl$gender_numddl$partner_wnc_x_gender <- ddl$partner_wnc * ddl$gender_numcat("Long format:", nrow(ddl), "rows\n")cat("Gender distribution:\n")print(table(ddl$gender))```## Baseline: two-level SEM without gender moderationPlace the four within-dyad predictors at the within level and thetwo dyad-level covariates at the between level. The two-level SEMis the SEM analogue of the [MLM tutorial](mlm-moderator.html).```{r}#| label: baseline-2levelmodel_base <-' level: within satisfaction ~ a_w*wnc + p_w*partner_wnc + ar_w*recovery + pr_w*partner_recovery level: between satisfaction ~ c_child*has_children + c_dual*dual_earner'fit_base <-sem(model_base, data = ddl, cluster ="dyad_id")summary(fit_base, standardized =TRUE, fit.measures =TRUE)```## Add gender × predictor interactionsThe within-dyad level now includes the gender main effect and thegender × actor/partner WNC interactions. The between-dyad levelis unchanged.```{r}#| label: moderator-2levelmodel_moderator <-' level: within satisfaction ~ a_w*wnc + p_w*partner_wnc + ar_w*recovery + pr_w*partner_recovery + g_w*gender_num + aw_int*wnc_x_gender + pw_int*partner_wnc_x_gender level: between satisfaction ~ c_child*has_children + c_dual*dual_earner # ── Simple slopes ────────────────────────────── # gender_num = 1 (male), gender_num = 2 (female) # Actor WNC → satisfaction ss_wnc_M := a_w + aw_int * 1 ss_wnc_F := a_w + aw_int * 2 # Partner WNC → satisfaction ss_pwnc_M := p_w + pw_int * 1 ss_pwnc_F := p_w + pw_int * 2'fit_moderator <-sem(model_moderator, data = ddl, cluster ="dyad_id")summary(fit_moderator, standardized =TRUE, fit.measures =TRUE)```## Reading the calculated simple slopesThe `:=` operator in `lavaan` defines a user-calculated parameter.The simple slopes are functions of the base coefficient and theinteraction coefficient, evaluated at the male and female valuesof `gender_num`.```{r}#| label: simple-slopespe <-parameterEstimates(fit_moderator)pe[grepl("^ss_", pe$label), c("label", "est", "se", "pvalue")]```::: {.callout-tip}## Comparing to the MLM estimatesThe within-dyad SEM `aw_int` coefficient (gender × actor WNC) and`pw_int` (gender × partner WNC) should match the corresponding`wnc:genderfemale` and `partner_wnc:genderfemale` interactions inthe [MLM moderator tutorial](mlm-moderator.html#step-3-likelihood-ratio-test).The simple slopes for males and females should also match the`sim_slopes()` output.:::## Why "model is saturated" matters hereThe two-level SEM with the within-dyad interactions has just-identifiedwithin-level equations: the four predictors plus three interactionterms and a gender main effect consume all the within-dyad degrees offreedom. This means:- The chi-square test of model fit is exactly zero (or near it) by construction.- The standard chi-square difference test is *not* available for comparing the baseline and moderator models.If you want a formal LRT, the right move is to fit both models inthe wide format (see the [SEM wide tutorial](sem-wide.html)), or touse the [MLM moderator approach](mlm-moderator.html#step-3-likelihood-ratio-test),where the LRT is well-defined.## What to take away::: {.callout-takeaway}## Key takeaways- The two-level SEM makes the within/between decomposition of effects explicit.- Gender × predictor interactions live at the within-dyad level.- Dyad-level covariates (no within-dyad variance) live at the between-dyad level.- Calculated simple slopes via `:=` give you the conditional effects at each level of the moderator.- The model is just-identified within-dyad, so the chi-square LRT is not available; use the MLM version for hypothesis testing.:::## What to read next- The [SEM wide tutorial](sem-wide.html) — wide format, the three-model sequence, the k-pattern tests.- The [two-intercept tutorial](two-intercept.html) — a parameterisation trick that estimates both intercepts directly.- The [Hahn et al. (2014) replication tutorial](../moderated/hahn2014.html) — moderated APIM with a dyad-level moderator.