1  A Quick Overview on Multi-Group SEM Workflow

This chapter is for users who are already familiar with standard SEM methods in R using the lavaan package to demonstrate how ggsem can expand the existing workflow significantly.

Here, I will show you a quick workflow of visualizing a multi-group SEM diagram in two principal types (side-by-side composite figure or combined SEM). The ggsem app can be launched by ggsem() code, opening up a blank canvas where users can draw diagrams (see next chapter).

library(ggsem)
ggsem()

Instead of opening the app in blank canvas, ggsem app can also be launched by loading pre-existing objects, such as multi-group SEM lavaan objects (or other types), using the pipe operator |> or %>%. This will launch the app with pre-drawn diagrams.

library(tidyverse)
library(ggsem)
library(lavaan)
lavaan_string <- "visual  =~ x1 + x2 + x3
textual =~ x4 + x5 + x6
speed   =~ x7 + x8 + x9"

(fit <- sem(lavaan_string, data = HolzingerSwineford1939, group = 'school'))
lavaan 0.6-19 ended normally after 57 iterations

  Estimator                                         ML
  Optimization method                           NLMINB
  Number of model parameters                        60

  Number of observations per group:                   
    Pasteur                                        156
    Grant-White                                    145

Model Test User Model:
                                                      
  Test statistic                               115.851
  Degrees of freedom                                48
  P-value (Chi-square)                           0.000
  Test statistic for each group:
    Pasteur                                     64.309
    Grant-White                                 51.542

fit is a fitted lavaan object containing the results of a multi-group SEM. The model, specified by lavaan_string, is estimated separately for each level of the school grouping variable in the HolzingerSwineford1939 dataset, allowing for the examination of measurement or structural invariance across the two schools.

ggsem_builder() |>
  add_group(name = "Pasteur", object = fit, x = -35) |>
  add_group(name ="Grant-White", object = fit, x = 35) |>
  launch()

ggsem_builder() sets up the object, and you can add_group() using the same multi-group lavaan object. You can define the name of each group to be identical to the group name in the data. Then, launch() the app with pre-loaded model objects.

1. ggsem_builder() - Initialization

ggsem_builder()
  • Initiates ggsem pipe builder workflow.

  • At this stage, the plot is essentially a blank slate waiting for SEM elements

2. add_group() - Multi-group Model Integration

|> add_group(name = "Pasteur", object = fit, x = -35)
  • name = "Pasteur": Matches one of the group names from your original lavaan model (lavInspect(fit, "group.label"))

  • object = fit: The fitted multi-group SEM object containing all parameter estimates and model specifications

  • x = -35: Positions this group’s diagram 35 units to the left of center for clear visual separation

What happens internally:

  • Extracts the model specification and parameter estimates for the “Pasteur” group from the fit object

  • Automatically draws all latent variables, observed variables, factor loadings, etc

  • Applies consistent styling and layout algorithms

  • Positions the entire sub-model at the specified x-coordinate

3. Second add_group() - Parallel Group Addition

|> add_group(name = "Grant-White", object = fit, x = 35)
  • Repeats the same extraction process for the second school group

  • Positions this diagram 35 units to the right of center

  • Maintains identical visual styling and scaling for direct comparison

  • The x-positioning (-35 vs +35) creates a side-by-side comparison layout

4. launch() - Interactive Application Launch

|> launch()
  • Opens the Shiny-based interactive application

  • Crucially: Instead of a blank canvas, the app opens with both group diagrams pre-rendered and positioned

  • All the SEM elements are already drawn with their correct relationships

  • The user can immediately begin modifying, exploring, or customizing rather than building from scratch

1.1 Figure Outputs

The code above automatically loads two SEM diagrams into the canvas, where you can assign unique color palettes in the app.

Figure 1. Two SEM diagrams with unique color palettes

Since ggsem directly has access to the model statistics, it can also highlight paths that are significantly different between two groups (schools).

Figure 2. Two SEM diagrams with highlighted paths that are significantly different

Through interactive parameter visualization, you can change any visual aspects while keeping the model intact. Here, the aesthetics of the textual node have been modified.

Figure 3. Interactive parameter visualization: Interactively modify the aesthetics of parameter ‘textual’ node through a dynamic dropdown

Figure 4. Two SEM diagrams whose ‘textual’ nodes’ aesthetics have been modified through interactive parameter visualization

Finally, group labels can automatically be added based on the groups’ name introduced in add_group().

Figure 5. Two SEM diagrams whose Texture nodes’ aesthetics have been modified through interactive parameter visualization

You can also combine the two SEM diagrams into one diagram, and align edge labels side-by-side.

Figure 6. Combine multiple SEMs across groups into one

Figure 7. A combined SEM diagram with aligned edge labels

Notice that the edge label of the path between visual and speed nodes overlap with the edge label between textual node and its intercept. So we can increase the curvature of the curved line. The path is colored in blue to highlight the change. These are achieved via interactive parameter visualization.

Figure 8. Interactive parameter visualization: Interactively modify the aesthetics of edge between visual and speed nodes through a dynamic dropdown

Figure 9. A combined SEM diagram with aligned edge labels

You can replay this workflow using undo and redo buttons in the app menu by loading the metadata (that I have created from this session) that app produces.

ggsem() # run the app and load the metadata

Figure 10. Load metadata (RDS) file and replay the session’s history

To reproduce Figure 5, you can download the metadata from online, and load it in the app.

www.smin95.com/fig5.rds

This image can also be loaded in script-based workflow using these codes below into a ggplot output directly using the metadata (more information in Chapter 17).

library(tidyverse)
library(ggsem)

metadata_fig5 <- readRDS('fig5.rds') # load the metadata from your directory
fig5 <- metadata_to_ggplot(metadata_fig5) # convert the metadata to a ggplot object
save_figure('fig5.png', fig5)

Figure 11. SEM figure saved from script-based workflow by loading metadata via code

If this workflow interests you, please continue to read the book. The next chapter describes the ggsem app in general, which is straightforward to use.