---
lang: en-GB
title: "EFA, CFA, CB-SEM, and PLS-SEM syntax generation"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{EFA, CFA, CB-SEM, and PLS-SEM syntax generation}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{=html}
<style>
/* WCAG 2.2 AA pass: darker link and syntax-token colours (at least
   4.5:1 on the #f7f7f7 code background), wrapped code lines instead of a
   keyboard-inaccessible scroll region, empty per-line anchors removed from
   the accessibility tree, and 24px minimum TOC link targets. */
a { color: #0e7c7a; }
code span.at { color: #576419; }
code span.dv, code span.fl, code span.bn { color: #276245; }
code span.co { color: #396a80; }
/* Pandoc emits `pre > code.sourceCode { white-space: pre }` for screen, which
   outranks a bare `pre code` rule on specificity, so source chunks have to be
   named explicitly or they scroll sideways instead of wrapping. */
pre, pre code, pre > code.sourceCode { white-space: pre-wrap; word-break: break-word; }
pre > code.sourceCode > span { text-indent: -2em; padding-left: 2em; }
div.sourceCode { overflow: visible; }
pre.sourceCode a:empty { display: none; }
#TOC a { display: inline-block; min-height: 24px; }
</style>
```

```{r setup, include = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
library(surveyframe)
```

The model is the third part of the research design. surveyframe stores the
measurement and structural specification and writes the syntax for the modelling
stage. It does not fit the models. This vignette builds the three models from
the published Thailand study (Sharafuddin, Madhavan, and Wangtueai 2024). The
syntax steps need no raw data, so every chunk below runs as written.

There are five constructs. Digital marketing effectiveness (DME) is built from
relevance and engagement (DMRE), accessibility and usefulness (DMAU), ease of use
(DMEU), and perceived value (DMPV). Destination service quality (DSQ) is built
from accommodation (DSQA) and local transport (DSQT). The remaining three are
destination sustainability quality (DSUQ), tourist satisfaction (TS), and
behavioural intention (BI).

```{r item-ids}
dmre <- paste0("dmre_", 1:4); dmau <- paste0("dmau_", 1:3)
dmeu <- paste0("dmeu_", 1:3); dmpv <- paste0("dmpv_", 1:4)
dsqa <- paste0("dsqa_", 1:3); dsqt <- paste0("dsqt_", 1:5)
dsuq <- paste0("dsuq_", 1:5); ts <- paste0("ts_", 1:3); bi <- paste0("bi_", 1:3)
```

## EFA planning syntax

`efa_syntax()` writes a short R block that estimates an exploratory factor
solution with the optional `psych` package. This screens the digital marketing
items before the confirmatory model.

```{r efa-syntax}
cat(efa_syntax(items = c(dmre, dmau, dmeu, dmpv), nfactors = 4,
               extraction = "minres", rotation = "oblimin"))
```

## CFA syntax: the lower-order measurement model

The confirmatory measurement model has the nine lower-order constructs as
reflective factors. `cfa_lavaan_syntax()` writes lavaan syntax from a model
object, with no need for lavaan at this stage.

```{r cfa}
construct_def <- list(
  DMRE = dmre, DMAU = dmau, DMEU = dmeu, DMPV = dmpv,
  DSQA = dsqa, DSQT = dsqt, DSUQ = dsuq, TS = ts, BI = bi
)

cfa_model <- sf_model(
  id    = "lower_order_cfa",
  label = "Lower-order measurement model",
  type  = "cfa",
  constructs = Map(function(id, items) sf_construct(id, id, items),
                   names(construct_def), construct_def)
)

cat(cfa_lavaan_syntax(model = cfa_model))
```

## CB-SEM syntax: the structural model

The covariance-based reading treats the five constructs as first-order
reflective factors over their full item sets, with the nine direct paths and the
four indirect effects from the hypotheses. `sem_lavaan_syntax()` writes the
measurement, structural, and indirect-effect lines.

```{r cbsem}
sem_model <- sf_model(
  id    = "tourism_structural",
  label = "Digital marketing structural model",
  type  = "cb_sem",
  constructs = list(
    sf_construct("DME",  "Digital marketing effectiveness", c(dmre, dmau, dmeu, dmpv)),
    sf_construct("DSQ",  "Destination service quality",     c(dsqa, dsqt)),
    sf_construct("DSUQ", "Destination sustainability quality", dsuq),
    sf_construct("TS",   "Tourist satisfaction", ts),
    sf_construct("BI",   "Behavioural intention", bi)
  ),
  paths = list(
    sf_path("DME", "DSQ", label = "h1"),  sf_path("DME", "DSUQ", label = "h2"),
    sf_path("DME", "TS",  label = "h3"),  sf_path("DME", "BI",   label = "h4"),
    sf_path("DSQ", "TS",  label = "h5"),  sf_path("DSQ", "BI",   label = "h6"),
    sf_path("DSUQ", "TS", label = "h7"),  sf_path("DSUQ", "BI",  label = "h8"),
    sf_path("TS", "BI",   label = "h9")
  ),
  indirect = list(
    sf_indirect("DME", "DSQ", "TS",  label = "h10"),
    sf_indirect("DME", "DSUQ", "TS", label = "h11"),
    sf_indirect("DME", c("DSQ", "TS"), "BI",  label = "h12"),
    sf_indirect("DME", c("DSUQ", "TS"), "BI", label = "h13")
  ),
  options = list(estimator = "MLR", missing = "fiml", standardised = TRUE)
)

validate_model(sem_model)
cat(sem_lavaan_syntax(sem_model))
```

## PLS-SEM syntax: the two-stage higher-order model

The published study used PLS-SEM with a two-stage treatment of the higher-order
constructs. The second stage models digital marketing effectiveness and service
quality as composites of their lower-order construct scores, then estimates the
structural paths. `seminr_syntax()` writes the seminr code, including the
bootstrap, reliability, AVE, and HTMT calls.

```{r pls}
pls_model <- sf_model(
  id    = "tourism_pls",
  label = "Two-stage higher-order PLS model",
  type  = "pls_sem",
  constructs = list(
    sf_construct("DME",  "Digital marketing effectiveness",
                 c("DMRE", "DMAU", "DMEU", "DMPV"), mode = "composite"),
    sf_construct("DSQ",  "Destination service quality",
                 c("DSQA", "DSQT"), mode = "composite"),
    sf_construct("DSUQ", "Destination sustainability quality", dsuq, mode = "composite"),
    sf_construct("TS",   "Tourist satisfaction", ts, mode = "composite"),
    sf_construct("BI",   "Behavioural intention", bi, mode = "composite")
  ),
  paths = list(
    sf_path("DME", "DSQ"), sf_path("DME", "DSUQ"),
    sf_path("DME", "TS"),  sf_path("DME", "BI"),
    sf_path("DSQ", "TS"),  sf_path("DSQ", "BI"),
    sf_path("DSUQ", "TS"), sf_path("DSUQ", "BI"),
    sf_path("TS", "BI")
  ),
  options = list(bootstrap = 1000)
)

cat(seminr_syntax(pls_model))
```

## Construct modes

A construct's mode is `reflective`, `composite`, `formative`, or `single_item`.
lavaan syntax generation is intended for reflective measurement models, which
is why the CFA and CB-SEM models use the default reflective mode. PLS-SEM
syntax uses composite constructs, as above.

## Model JSON and a reporting template

A model serialises to JSON for storage in a `.sframe` file, and
`model_report_template()` writes a short reporting outline.

```{r json}
cat(model_report_template(sem_model, include_json = FALSE))
```

## Where the syntax goes next

The generated lavaan syntax is copied into `lavaan::cfa()` or `lavaan::sem()`
after choosing the estimator, ordered-item handling, and missing-data treatment.
The generated seminr syntax is copied into a script where seminr is installed and
the bootstrap settings and construct modes are set. The published study fitted
the two-stage PLS model in seminr with 1000 bootstrap resamples.
