diff --git a/src/StructuralEquationModels.jl b/src/StructuralEquationModels.jl index f6068dc5..5d0bb774 100644 --- a/src/StructuralEquationModels.jl +++ b/src/StructuralEquationModels.jl @@ -83,6 +83,7 @@ include("frontend/fit/fitmeasures/minus2ll.jl") include("frontend/fit/fitmeasures/p.jl") include("frontend/fit/fitmeasures/RMSEA.jl") include("frontend/fit/fitmeasures/fit_measures.jl") +include("frontend/fit/fitmeasures/explained_variance.jl") # standard errors include("frontend/fit/standard_errors/hessian.jl") include("frontend/fit/standard_errors/bootstrap.jl") @@ -178,6 +179,7 @@ export AbstractSem, param_indices, param_labels, fit_measures, + explained_variance, AIC, BIC, χ², diff --git a/src/frontend/fit/explained_variance.jl b/src/frontend/fit/explained_variance.jl new file mode 100644 index 00000000..0b5dbd86 --- /dev/null +++ b/src/frontend/fit/explained_variance.jl @@ -0,0 +1,30 @@ + +""" +explained_variance(fitted) + +Compute explained variance (R²) for each observed variable in a fitted SEM. + +Returns a DataFrame with: +- :var — observed variable name (Symbol) +- :r2_implied — 1 - ( residual variance / model-implied variance) + +""" +function explained_variance(fitted::SemFit) +# 1) Observed variable order as used by the model +obs = Symbol.(fitted.model.observed.observed_vars) + +# 2) Model-implied covariance (diagonal are model-implied total variances) +Σ_imp = fitted.model.implied.Σ +var_imp = diag(Σ_imp) + +# 3) Get model-implied variances of observed variables +resvars = diag(fitted.model.implied.F*fitted.model.implied.S*transpose(fitted.model.implied.F)) + +# 4) Compute R² (model-implied) +r2_imp = 1 .- (resvars ./ var_imp) + +# prepare return object +df = DataFrame(var = obs, r2_implied = r2_imp) +return df + +end