These lines might be the culprit. The implementation seems to drop the equality constraint?
So lavaan sets these two parameters free when auto.fix.first = FALSE, which is correct behavior which is picked up in add_paths, but because of the dropped == the model actually does not constrain them to be equal despite the fact they have identical labels, leading to non-convergence.
auto.fix.first = TRUE does set them to equality because it fixes them all to 1.
library(tidySEM)
#> Loading required package: OpenMx
#> Registered S3 method overwritten by 'tidySEM':
#> method from
#> predict.MxModel OpenMx
x <- as.data.frame(MASS::mvrnorm(n = 100,
mu = c(0, 0, 0),
Sigma = matrix(c(1.00, 0.60, 0.50,
0.60, 1.00, 0.70,
0.50, 0.70, 1.00),
ncol = 3), empirical = F))
colnames(x) <- c("f_1", "f_2", "f_3")
# Notice the unstandardized parameters are not equal, even though the labels are equal
lavaan::summary(run_lavaan(
add_paths(tidy_sem(x),
c("f =~ f_eq*f_1", "f =~ f_eq*f_2", "f =~ f_eq*f_3"),
auto.fix.first = F,
std.lv = T)
), standardized = T)
#> lavaan 0.6.15 ended normally after 13 iterations
#>
#> Estimator ML
#> Optimization method NLMINB
#> Number of model parameters 9
#>
#> Number of observations 100
#>
#> Model Test User Model:
#>
#> Test statistic 0.000
#> Degrees of freedom 0
#>
#> Parameter Estimates:
#>
#> Standard errors Standard
#> Information Expected
#> Information saturated (h1) model Structured
#>
#> Latent Variables:
#> Estimate Std.Err z-value P(>|z|) Std.lv Std.all
#> f =~
#> f_1 (f_eq) 0.603 0.092 6.562 0.000 0.603 0.630
#> f_2 (f_eq) 0.999 0.097 10.285 0.000 0.999 0.934
#> f_3 (f_eq) 0.824 0.097 8.509 0.000 0.824 0.795
#>
#> Intercepts:
#> Estimate Std.Err z-value P(>|z|) Std.lv Std.all
#> .f_1 0.123 0.096 1.283 0.199 0.123 0.128
#> .f_2 0.072 0.107 0.669 0.503 0.072 0.067
#> .f_3 0.047 0.104 0.457 0.648 0.047 0.046
#> f 0.000 0.000 0.000
#>
#> Variances:
#> Estimate Std.Err z-value P(>|z|) Std.lv Std.all
#> .f_1 0.555 0.088 6.306 0.000 0.555 0.604
#> .f_2 0.146 0.111 1.316 0.188 0.146 0.128
#> .f_3 0.395 0.093 4.254 0.000 0.395 0.368
#> f 1.000 1.000 1.000
# Here they are equal, but they are also fixed to `1`
lavaan::summary(run_lavaan(
add_paths(tidy_sem(x),
c("f =~ f_eq*f_1", "f =~ f_eq*f_2", "f =~ f_eq*f_3"),
auto.fix.first = T)
), standardized = T)
#> lavaan 0.6.15 ended normally after 15 iterations
#>
#> Estimator ML
#> Optimization method NLMINB
#> Number of model parameters 7
#>
#> Number of observations 100
#>
#> Model Test User Model:
#>
#> Test statistic 12.583
#> Degrees of freedom 2
#> P-value (Chi-square) 0.002
#>
#> Parameter Estimates:
#>
#> Standard errors Standard
#> Information Expected
#> Information saturated (h1) model Structured
#>
#> Latent Variables:
#> Estimate Std.Err z-value P(>|z|) Std.lv Std.all
#> f =~
#> f_1 (f_eq) 1.000 0.830 0.754
#> f_2 (f_eq) 1.000 0.830 0.831
#> f_3 (f_eq) 1.000 0.830 0.814
#>
#> Intercepts:
#> Estimate Std.Err z-value P(>|z|) Std.lv Std.all
#> .f_1 0.123 0.110 1.116 0.264 0.123 0.112
#> .f_2 0.072 0.100 0.716 0.474 0.072 0.072
#> .f_3 0.047 0.102 0.464 0.642 0.047 0.046
#> f 0.000 0.000 0.000
#>
#> Variances:
#> Estimate Std.Err z-value P(>|z|) Std.lv Std.all
#> .f_1 0.524 0.094 5.570 0.000 0.524 0.432
#> .f_2 0.310 0.069 4.492 0.000 0.310 0.310
#> .f_3 0.351 0.073 4.785 0.000 0.351 0.337
#> f 0.690 0.116 5.945 0.000 1.000 1.000
https://github.com/cjvanlissa/tidySEM/blob/master/R/syntax-add_paths.R#L121-L127
These lines might be the culprit. The implementation seems to drop the equality constraint?
So lavaan sets these two parameters free when auto.fix.first = FALSE, which is correct behavior which is picked up in add_paths, but because of the dropped
==
the model actually does not constrain them to be equal despite the fact they have identical labels, leading to non-convergence.auto.fix.first = TRUE does set them to equality because it fixes them all to
1
.Created on 2023-06-22 with reprex v2.0.2