---
title: "Tabulating results from structural equation models"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Tabulating results from structural equation models}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
run_mplus <- FALSE
```

```{r setup}
library(tidySEM)
library(lavaan)
library(MplusAutomation)
library(dplyr)
```

`tidySEM` tabulates the results of different types of models in the same uniform way. This facilitates parsing the output into Tables and Figures for publication.

## Output from lavaan

As an example, let's tabulate the results from a classic `lavaan` tutorial example for a multiple group model. First, we run the model:

```{r}
HS.model <- '  visual =~ x1 + x2 + x3
              textual =~ x4 + x5 + x6
              speed   =~ x7 + x8 + x9 '
fit <- cfa(HS.model, 
           data = HolzingerSwineford1939, 
           group = "school")
```
The results can be tabulated using the `lavaan` function `summary()`:

```{r}
summary(fit)
```

Alternatively, we can use the `tidySEM` function `table_results()`:

```{r}
table_results(fit)
```

## Output from Mplus

Now, we'll reproduce the same analysis in 'Mplus'. The `tidySEM` package has a function `measurement()` to generate measurement models automatically. However, to illustrate the fact that `tidySEM` is compatible with existing solutions, we will specify the syntax for this example manually, using the package `MplusAutomation`. This code will only work on your machine if you have Mplus installed and R can find it. First, we run the model:

```{r, eval = FALSE, echo = TRUE}
fit <- mplusModeler(mplusObject(VARIABLE = "grouping IS school (1 = GW 2 = Pas);",
                                MODEL = c("visual BY x1 x2 x3;",
                                          "textual BY x4 x5 x6;",
                                          "speed BY x7 x8 x9;"),
                                usevariables = c(paste0("x", 1:9), "school"),
                                rdata = HolzingerSwineford1939),
                    modelout = "example.inp",
                    run = 1L)
fit$results$parameters
```
```{r, eval = run_mplus, echo = FALSE}
# fit <- mplusModeler(mplusObject(VARIABLE = "grouping IS school (1 = GW 2 = Pas);",
#                                 MODEL = c("visual BY x1 x2 x3;",
#                                           "textual BY x4 x5 x6;",
#                                           "speed BY x7 x8 x9;"),
#                                 usevariables = c(paste0("x", 1:9), "school"),
#                                 rdata = HolzingerSwineford1939),
#                     modelout = "example.inp",
#                     run = 1L)
# file.remove(list.files(pattern = "^example.+(inp|out|dat)$"))
#dput(fit$results$parameters)
```
```{r eval = TRUE, echo = FALSE}
# Read the results
fit <- list(results = list(parameters = list(unstandardized = structure(list(
    paramHeader = c("VISUAL.BY", "VISUAL.BY", "VISUAL.BY", "TEXTUAL.BY", 
    "TEXTUAL.BY", "TEXTUAL.BY", "SPEED.BY", "SPEED.BY", "SPEED.BY", 
    "TEXTUAL.WITH", "SPEED.WITH", "SPEED.WITH", "Means", "Means", 
    "Means", "Intercepts", "Intercepts", "Intercepts", "Intercepts", 
    "Intercepts", "Intercepts", "Intercepts", "Intercepts", "Intercepts", 
    "Variances", "Variances", "Variances", "Residual.Variances", 
    "Residual.Variances", "Residual.Variances", "Residual.Variances", 
    "Residual.Variances", "Residual.Variances", "Residual.Variances", 
    "Residual.Variances", "Residual.Variances", "VISUAL.BY", 
    "VISUAL.BY", "VISUAL.BY", "TEXTUAL.BY", "TEXTUAL.BY", "TEXTUAL.BY", 
    "SPEED.BY", "SPEED.BY", "SPEED.BY", "TEXTUAL.WITH", "SPEED.WITH", 
    "SPEED.WITH", "Means", "Means", "Means", "Intercepts", "Intercepts", 
    "Intercepts", "Intercepts", "Intercepts", "Intercepts", "Intercepts", 
    "Intercepts", "Intercepts", "Variances", "Variances", "Variances", 
    "Residual.Variances", "Residual.Variances", "Residual.Variances", 
    "Residual.Variances", "Residual.Variances", "Residual.Variances", 
    "Residual.Variances", "Residual.Variances", "Residual.Variances"
    ), param = c("X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", 
    "X9", "VISUAL", "VISUAL", "TEXTUAL", "VISUAL", "TEXTUAL", 
    "SPEED", "X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", 
    "X9", "VISUAL", "TEXTUAL", "SPEED", "X1", "X2", "X3", "X4", 
    "X5", "X6", "X7", "X8", "X9", "X1", "X2", "X3", "X4", "X5", 
    "X6", "X7", "X8", "X9", "VISUAL", "VISUAL", "TEXTUAL", "VISUAL", 
    "TEXTUAL", "SPEED", "X1", "X2", "X3", "X4", "X5", "X6", "X7", 
    "X8", "X9", "VISUAL", "TEXTUAL", "SPEED", "X1", "X2", "X3", 
    "X4", "X5", "X6", "X7", "X8", "X9"), est = c(1, 0.576, 0.798, 
    1, 1.12, 0.932, 1, 1.13, 1.009, 0.427, 0.329, 0.236, 0, 0, 
    0, 4.854, 6.066, 2.153, 3.354, 4.68, 2.463, 4.065, 5.43, 
    5.286, 0.708, 0.87, 0.505, 0.654, 0.964, 0.641, 0.343, 0.376, 
    0.437, 0.625, 0.434, 0.522, 1, 0.576, 0.798, 1, 1.12, 0.932, 
    1, 1.13, 1.009, 0.41, 0.178, 0.18, 0.148, -0.576, 0.177, 
    4.854, 6.066, 2.153, 3.354, 4.68, 2.463, 4.065, 5.43, 5.286, 
    0.796, 0.879, 0.322, 0.555, 1.296, 0.944, 0.445, 0.502, 0.263, 
    0.888, 0.541, 0.654), se = c(0, 0.109, 0.13, 0, 0.066, 0.057, 
    0, 0.137, 0.16, 0.098, 0.084, 0.075, 0, 0, 0, 0.094, 0.077, 
    0.084, 0.088, 0.098, 0.084, 0.083, 0.083, 0.078, 0.162, 0.133, 
    0.119, 0.131, 0.127, 0.113, 0.064, 0.074, 0.068, 0.103, 0.101, 
    0.101, 0, 0.109, 0.13, 0, 0.066, 0.057, 0, 0.137, 0.16, 0.107, 
    0.067, 0.063, 0.127, 0.117, 0.094, 0.094, 0.077, 0.084, 0.088, 
    0.098, 0.084, 0.083, 0.083, 0.078, 0.192, 0.132, 0.085, 0.157, 
    0.161, 0.148, 0.072, 0.086, 0.051, 0.127, 0.099, 0.101), 
    est_se = c(999, 5.262, 6.139, 999, 16.962, 16.315, 999, 8.258, 
    6.326, 4.366, 3.932, 3.154, 999, 999, 999, 51.772, 78.581, 
    25.726, 38.162, 47.941, 29.285, 49.067, 65.788, 67.679, 4.382, 
    6.55, 4.249, 4.973, 7.573, 5.685, 5.397, 5.101, 6.389, 6.078, 
    4.308, 5.192, 999, 5.262, 6.139, 999, 16.962, 16.315, 999, 
    8.258, 6.326, 3.844, 2.657, 2.867, 1.164, -4.935, 1.884, 
    51.772, 78.581, 25.726, 38.162, 47.941, 29.285, 49.067, 65.788, 
    67.679, 4.146, 6.654, 3.786, 3.539, 8.071, 6.399, 6.209, 
    5.859, 5.124, 7.006, 5.483, 6.476), pval = c(999, 0, 0, 999, 
    0, 0, 999, 0, 0, 0, 0, 0.002, 999, 999, 999, 0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 999, 0, 
    0, 999, 0, 0, 999, 0, 0, 0, 0.008, 0.004, 0.244, 0, 0.06, 
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    0, 0), Group = c("GW", "GW", "GW", "GW", "GW", "GW", "GW", 
    "GW", "GW", "GW", "GW", "GW", "GW", "GW", "GW", "GW", "GW", 
    "GW", "GW", "GW", "GW", "GW", "GW", "GW", "GW", "GW", "GW", 
    "GW", "GW", "GW", "GW", "GW", "GW", "GW", "GW", "GW", "PAS", 
    "PAS", "PAS", "PAS", "PAS", "PAS", "PAS", "PAS", "PAS", "PAS", 
    "PAS", "PAS", "PAS", "PAS", "PAS", "PAS", "PAS", "PAS", "PAS", 
    "PAS", "PAS", "PAS", "PAS", "PAS", "PAS", "PAS", "PAS", "PAS", 
    "PAS", "PAS", "PAS", "PAS", "PAS", "PAS", "PAS", "PAS")), row.names = c(NA, 
-72L), class = c("data.frame", "mplus.params"), filename = "example.out"))))
class(fit) <- c("mplusObject", "list")
class(fit$results) <- c("mplus.model", "list")
fit$results$parameters
```

The results can be tabulated using the `MplusAutomation` function `coef.mplus.model()`:

```{r}
coef(fit)
```

Alternatively, we can use the `tidySEM` function `table_results()`:

```{r}
table_results(fit)
```
