---
title: "customizing interaction terms"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{customizing interaction terms}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

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

```{r setup, eval = TRUE}
library(modsem)
```

By default, `modsem()` creates product indicators for you based on the interaction specified in your model. Behind the scenes, `modsem()` generates a total of 9 variables (product indicators) that are used as the indicators for your latent product.

```{r}
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)
```

While this is often sufficient, you might want more control over how these indicators are created. In general, `modsem()` offers two mechanisms for controlling the creation of product indicators:
1. By specifying the measurement model for your latent product yourself.
2. By using the `mean()` and `sum()` functions, collectively known as parceling operations.

## Specifying the Measurement Model

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

```{r}
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

If you want even more control, you can use the `get_pi_syntax()` and `get_pi_data()` functions to extract the modified syntax and data from `modsem()`, allowing you to modify them as needed. This can be particularly useful in cases where you want to estimate a model using a feature in `lavaan` that isn't available in `modsem()`.

For example, the syntax for ordered and multigroup models (as of now) isn't as flexible in `modsem()` as it is in `lavaan`. You can modify the auto-generated syntax (along with the altered dataset) from `modsem()` to suit your needs.

```{r}
m3 <- '
# Outer Model
X =~ x1 + x2 + x3
Y =~ y1 + y2 + y3
Z =~ z1 + z2 + z3

# Inner model
Y ~ X + Z + X:Z
'
syntax <- get_pi_syntax(m3)
cat(syntax)
```

```{r}
data <- get_pi_data(m3, oneInt)
head(data)
```

The generated syntax and data can then be used to estimate a model using `lavaan`, giving the
user more control over arguments passed onto `lavaan::sem()`, and potentially the ability to
modify the the generated syntax and data.

```{r}
library(lavaan)
fit <- sem(syntax, data = data, fixed.x = FALSE,
           std.lv = TRUE, auto.fix.first = TRUE,
           auto.var = TRUE, auto.cov.lv.x = TRUE)
summary(fit)
```
