customizing interaction terms

library(modsem)

By default, modsem() creates product indicators for you, based on the interaction specified in your model. Behind the scenes we can see that modsem() creates in total 9 variables (product indicators) used as the indicators for your latent product.

m1 <- '
# Outer Model
X =~ x1 + x2 + x3
Y =~ y1 + y2 + y3
Z =~ z1 + z2 + z3

# Inner model
Y ~ X + Z + X:Z 
'

est1 <- modsem(m1, oneInt)
cat(est1$syntax)

Whilst this often is sufficient, you might want some control over how these indicators are created. In general, modsem() has two mechanisms for giving control over the creating of indicator products: 1. By specifying the measurement model of your latent product your self, and 2. By using the mean() and sum() function, collectively known as parceling operations.

Specifying The Measurement Model

By default, modsem() creates all possible combinations of different product indicators. However, another common approach is to match the indicators by order. For example, let’s say you have an interaction between the laten variables X and Z: ‘X =~ x1 + x2’ and ‘Z =~ z1 + z2’. By default you would get ‘XZ =~ x1z1 + x1z2 + x2z1 + x2z2’. If you wanted to use the matching approach you would want to get ‘XZ =~ x1z1 + x2z2’ instead. To achieve this you can use the ‘match = TRUE’ argument.

m2 <- '
# Outer Model
X =~ x1 + x2
Y =~ y1 + y2
Z =~ z1 + z2

# Inner model
Y ~ X + Z + X:Z 
'

est2 <- modsem(m2, oneInt, match = TRUE)
summary(est2)

More complicated models

I you want even more control you can use the get_pi_syntax() and get_pi_data() functions, such that you can extract the modified syntax and data from modsem, and alter them accordingly. This can be particularly useful in cases where you want to estimate a model using a feature in lavaan, which isn’t available in modsem. For example, (as of yet) the syntax for both ordered- and multigroup models isn’t as flexible as in lavaan. Thus you can modify the auto-generated syntax (with the altered dataset) from modsem to suit your needs.

m3 <- '
# Outer Model
X =~ x1 + x2
Y =~ y1 + y2
Z =~ z1 + z2

# Inner model
Y ~ X + Z + X:Z 
'
syntax <- get_pi_syntax(m3)
cat(syntax)
#> X =~ x1
#> X =~ x2
#> Y =~ y1
#> Y =~ y2
#> Z =~ z1
#> Z =~ z2
#> Y ~ X
#> Y ~ Z
#> Y ~ XZ
#> XZ =~ 1*x1z1
#> XZ =~ x2z1
#> XZ =~ x1z2
#> XZ =~ x2z2
#> x1z1 ~~ 0*x2z2
#> x1z2 ~~ 0*x2z1
#> x1z1 ~~ x1z2
#> x1z1 ~~ x2z1
#> x1z2 ~~ x2z2
#> x2z1 ~~ x2z2
data <- get_pi_data(m3, oneInt)
head(data)
#>           x1         x2         y1         y2         z1         z2       x1z1
#> 1  2.4345722  1.3578655  1.4526897  0.9560888  0.8184825 1.60708140 -0.4823019
#> 2  0.2472734  0.2723201  0.5496756  0.7115311  3.6649148 2.60983102 -2.2680403
#> 3 -1.3647759 -0.5628205 -0.9835467 -0.6697747  1.7249386 2.10981827 -1.9137416
#> 4  3.0432836  2.2153763  6.4641465  4.7805981  2.5697116 3.26335379  2.9385205
#> 5  2.8148841  2.7029616  2.2860280  2.1457643  0.3467850 0.07164577 -1.4009548
#> 6 -0.5453450 -0.7530642  1.1294876  1.1998472 -0.2362958 0.60252657  1.7465860
#>         x2z1       x1z2       x2z2
#> 1 -0.1884837  0.3929380 -0.0730934
#> 2 -2.6637694 -1.2630544 -1.4547433
#> 3 -1.4299711 -2.3329864 -1.7383407
#> 4  1.3971422  3.9837389  1.9273102
#> 5 -1.1495704 -2.2058995 -1.8169042
#> 6  2.2950753  0.7717365  1.0568143