# Exploring Factor Complexity with ESEM: Example 1

# Example 1: Estimating Factor Complexity in an ESEM Solution

This example demonstrates a full workflow for estimating factor complexity in an Exploratory Structural Equation Modeling (ESEM) context using the `facomplex` package. We use a two-factor target rotation on a set of 12 items. This is a real data, about motivations for research in university teachers

## 1. Load the data

We start by loading the dataset `fullclean` which should contain the observed variables for the ESEM model, 12 items, 2 factors.

    data(fullclean)

## 2. Create a target matrix

We define the hypothesized factor structure using a target matrix. This matrix guides the target rotation by specifying which items are expected to load on each factor.

    INV.target <- matrix(0, 12, 2)
    INV.target[1:6, 1] <- NA
    INV.target[7:12, 2] <- NA
    INV.target
    #>       [,1] [,2]
    #>  [1,]   NA    0
    #>  [2,]   NA    0
    #>  [3,]   NA    0
    #>  [4,]   NA    0
    #>  [5,]   NA    0
    #>  [6,]   NA    0
    #>  [7,]    0   NA
    #>  [8,]    0   NA
    #>  [9,]    0   NA
    #> [10,]    0   NA
    #> [11,]    0   NA
    #> [12,]    0   NA

## 3. Specify the ESEM model

Using `lavaan`, we define an ESEM model with exploratory factors `f1` and `f2`. All items load on both factors through exploratory syntax.

    INV.esem.model <- '
    efa("efa1")*f1 +
    efa("efa1")*f2 =~ INV1 + INV4 + INV5 + INV7 + INV11 + INV12 + INV3 + INV6 + INV8 + INV9 + INV13 + INV14
    '

## 4. Fit the ESEM model

We fit the model using the `sem()` function from `lavaan`, applying a target rotation based on our predefined matrix.

    INV.esem.fit <- sem(INV.esem.model,
                        data = fullclean,
                        ordered = FALSE,
                        estimator = "ulsmv",
                        rotation = "target",
                        rotation.args = list(target = INV.target,
                                             geomin.epsilon = 0.01,
                                             rstarts = 30,
                                             algorithm = "gpa",
                                             std.ov = TRUE))

We examine the model fit and standardized solution:

    summary(INV.esem.fit, standardized = TRUE, fit.measures = TRUE)
    #> lavaan 0.6-21 ended normally after 32 iterations
    #>
    #>   Estimator                                        ULS
    #>   Optimization method                           NLMINB
    #>   Number of model parameters                        37
    #>   Row rank of the constraints matrix                 2
    #>
    #>   Rotation method                          PST OBLIQUE
    #>   Rotation algorithm (rstarts)                GPA (30)
    #>   Standardized metric                             TRUE
    #>   Row weights                                     None
    #>
    #>                                                   Used       Total
    #>   Number of observations                           588         589
    #>
    #> Model Test User Model:
    #>                                               Standard      Scaled
    #>   Test Statistic                               118.607     152.535
    #>   Degrees of freedom                                43          43
    #>   P-value (Unknown)                                 NA       0.000
    #>   Scaling correction factor                                  0.846
    #>   Shift parameter                                           12.312
    #>     simple second-order correction
    #>
    #> Model Test Baseline Model:
    #>
    #>   Test statistic                              2868.367    1173.406
    #>   Degrees of freedom                                66          66
    #>   P-value                                           NA       0.000
    #>   Scaling correction factor                                  2.511
    #>
    #> User Model versus Baseline Model:
    #>
    #>   Comparative Fit Index (CFI)                    0.973       0.901
    #>   Tucker-Lewis Index (TLI)                       0.959       0.848
    #>
    #>   Robust Comparative Fit Index (CFI)                         0.967
    #>   Robust Tucker-Lewis Index (TLI)                            0.949
    #>
    #> Root Mean Square Error of Approximation:
    #>
    #>   RMSEA                                          0.055       0.066
    #>   90 Percent confidence interval - lower         0.043       0.055
    #>   90 Percent confidence interval - upper         0.067       0.077
    #>   P-value H_0: RMSEA <= 0.050                    0.240       0.010
    #>   P-value H_0: RMSEA >= 0.080                    0.000       0.021
    #>
    #>   Robust RMSEA                                               0.061
    #>   90 Percent confidence interval - lower                     0.050
    #>   90 Percent confidence interval - upper                     0.071
    #>   P-value H_0: Robust RMSEA <= 0.050                         0.045
    #>   P-value H_0: Robust RMSEA >= 0.080                         0.001
    #>
    #> Standardized Root Mean Square Residual:
    #>
    #>   SRMR                                           0.054       0.054
    #>
    #> Parameter Estimates:
    #>
    #>   Standard errors                           Robust.sem
    #>   Information                                 Expected
    #>   Information saturated (h1) model        Unstructured
    #>
    #> Latent Variables:
    #>                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
    #>   f1 =~ efa1
    #>     INV1              0.648    0.066    9.771    0.000    0.648    0.652
    #>     INV4              0.640    0.062   10.287    0.000    0.640    0.652
    #>     INV5              0.534    0.062    8.599    0.000    0.534    0.615
    #>     INV7              0.656    0.062   10.532    0.000    0.656    0.680
    #>     INV11             0.522    0.061    8.508    0.000    0.522    0.593
    #>     INV12             0.385    0.063    6.081    0.000    0.385    0.415
    #>     INV3              0.033    0.055    0.587    0.557    0.033    0.035
    #>     INV6              0.183    0.067    2.710    0.007    0.183    0.187
    #>     INV8              0.087    0.052    1.666    0.096    0.087    0.092
    #>     INV9              0.091    0.056    1.629    0.103    0.091    0.093
    #>     INV13            -0.110    0.051   -2.139    0.032   -0.110   -0.106
    #>     INV14            -0.101    0.064   -1.570    0.117   -0.101   -0.090
    #>   f2 =~ efa1
    #>     INV1             -0.037    0.062   -0.592    0.554   -0.037   -0.037
    #>     INV4             -0.108    0.052   -2.088    0.037   -0.108   -0.110
    #>     INV5             -0.036    0.058   -0.621    0.535   -0.036   -0.042
    #>     INV7              0.002    0.052    0.048    0.962    0.002    0.003
    #>     INV11             0.050    0.055    0.901    0.368    0.050    0.056
    #>     INV12             0.289    0.053    5.418    0.000    0.289    0.311
    #>     INV3              0.405    0.056    7.171    0.000    0.405    0.438
    #>     INV6              0.295    0.063    4.696    0.000    0.295    0.302
    #>     INV8              0.573    0.062    9.249    0.000    0.573    0.606
    #>     INV9              0.590    0.061    9.630    0.000    0.590    0.604
    #>     INV13             0.765    0.056   13.728    0.000    0.765    0.737
    #>     INV14             0.473    0.072    6.618    0.000    0.473    0.421
    #>
    #> Covariances:
    #>                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
    #>   f1 ~~
    #>     f2                0.595    0.051   11.763    0.000    0.595    0.595
    #>
    #> Variances:
    #>                    Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
    #>    .INV1              0.595    0.054   10.964    0.000    0.595    0.602
    #>    .INV4              0.623    0.056   11.060    0.000    0.623    0.647
    #>    .INV5              0.491    0.053    9.318    0.000    0.491    0.651
    #>    .INV7              0.499    0.046   10.747    0.000    0.499    0.535
    #>    .INV11             0.468    0.042   11.146    0.000    0.468    0.605
    #>    .INV12             0.497    0.040   12.481    0.000    0.497    0.577
    #>    .INV3              0.674    0.053   12.759    0.000    0.674    0.789
    #>    .INV6              0.765    0.058   13.197    0.000    0.765    0.806
    #>    .INV8              0.498    0.047   10.699    0.000    0.498    0.557
    #>    .INV9              0.533    0.042   12.846    0.000    0.533    0.559
    #>    .INV13             0.580    0.058    9.990    0.000    0.580    0.538
    #>    .INV14             1.088    0.072   15.061    0.000    1.088    0.860
    #>     f1                1.000                               1.000    1.000
    #>     f2                1.000                               1.000    1.000

## 5. Compute factor complexity indices

We now use the `facomplex` package to calculate various indices of factor complexity.

### Factor Simplicity Index (FSI)

The items grouped in both lists, within the `items_target` argument, are the expected items in their factors. The use of FSI to interpret its results at the factor level requires this prior knowledge of the items in their expected factors.

    simload(data = lavInspect(INV.esem.fit, what = "std")$lambda,
        items_target = list(f1 = c(1,2,3,4,5,6),
                            f2 = c(7,8,9,10,11,12)))
    #> $TSFI
    #> [1] 0.955
    #>
    #> $SFI
    #>    f1    f2
    #> 0.968 0.938
    #>
    #> $IFS
    #>    Items   IFS
    #> 1   INV1 0.997
    #> 2   INV4 0.972
    #> 3   INV5 0.995
    #> 4   INV7 1.000
    #> 5  INV11 0.991
    #> 6  INV12 0.439
    #> 7   INV3 0.994
    #> 8   INV6 0.616
    #> 9   INV8 0.977
    #> 10  INV9 0.976
    #> 11 INV13 0.979
    #> 12 INV14 0.954

### Hofmann’s Index

    Hofmann(data = lavInspect(INV.esem.fit, what = "std")$lambda)
    #>        CHof CHof_R
    #> INV1  1.006  0.994
    #> INV4  1.057  0.946
    #> INV5  1.009  0.991
    #> INV7  1.000  1.000
    #> INV11 1.018  0.982
    #> INV12 1.853  0.540
    #> INV3  1.013  0.987
    #> INV6  1.670  0.599
    #> INV8  1.046  0.956
    #> INV9  1.047  0.955
    #> INV13 1.041  0.960
    #> INV14 1.091  0.916

### Bentler’s Simplicity Index (BSI)

    BSI(lavInspect(INV.esem.fit, what = "std")$lambda)
    #> [1] 0.9969713

This concludes Example 1. Additional examples will build upon these procedures to showcase different model structures, datasets, and complexity conditions.