---
title: "A complete workflow: from sequences to a group comparison"
author:
  - "Mohammed Saqr"
  - "Sonsoles López-Pernas"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{A complete workflow: from sequences to a group comparison}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", message = FALSE,
                      warning = FALSE, dpi = 150, fig.width = 7,
                      fig.height = 5.6, out.width = "100%",
                      fig.align = "center")
set.seed(2026)
library(lagdynamics)
old_options <- options(digits = 3)
has_cograph <- requireNamespace("cograph", quietly = TRUE)
has_ggplot2 <- requireNamespace("ggplot2", quietly = TRUE)
```

This vignette shows a complete applied workflow: define the sequence
data, fit an LSA model, read the fitted transitions, visualise the main
structure, add uncertainty evidence, start from a raw event log, and
compare groups.

It assumes the method overview in `vignette("intro", package =
"lagdynamics")`. It uses only a small plotting subset; the full gallery
is in `vignette("plotting", package = "lagdynamics")`. The full
confirmatory battery is in `vignette("confirmatory", package =
"lagdynamics")`.

# Define the sequence data

`engagement` contains 138 students observed over 15 weekly time points.
Each row is one student sequence. Each cell is a weekly engagement state:
`Active`, `Average`, or `Disengaged`.

```{r data}
head(engagement)
```

This first step fixes the scope of the claim: the empirical units are
students, the events are weekly states, and the ordering is column order.

# Fit the model

`lsa()` estimates the transition table, the counts expected under
independence, and the adjusted residual for each transition. The
adjusted residual is the local test statistic: positive values mark
over-represented transitions and negative values mark avoided
transitions.

```{r fit}
fit <- lsa(engagement)
fit
```

# Read the fitted transitions

The fitted object is read through verbs. `transitions()` returns one row
per `from -> to` edge.

```{r read}
transitions(fit)
```

For interpretation, it is usually clearer to begin with transitions that
depart from chance.

```{r read-significant}
transitions(fit, significant = TRUE)
```

The companion tables keep the transition interpretation grounded in node
volume, starting states, and tablewise tests.

```{r read-context}
nodes(fit)
tests(fit)
initial(fit)
```

# Visualise the fitted model

The default plot is the residual heatmap. It displays the LSA model
directly: rows are source states, columns are target states, and colour
is the adjusted residual.

```{r heatmap, eval = has_ggplot2}
plot(fit)
```

The residual network shows the same departure-from-chance model as
directed edges.

```{r residual-network, eval = has_cograph}
plot(fit, type = "network")
```

A TNA-style transition network is a different view of the same process:
edge weights are conditional transition probabilities rather than
residuals.

```{r tna-network, eval = has_cograph}
plot(fit, type = "network", weights = "tna")
```

Use the plotting vignette for chord diagrams, sunbursts, comparison
heatmaps, and uncertainty plots.

# Add uncertainty evidence

An edge claim needs more than a fitted residual. `certainty_lsa()` gives
analytic credible intervals for transition probabilities.

```{r certainty}
cert <- certainty_lsa(fit)
cert
transitions(cert) |> head(4)
```

`bootstrap_lsa()` resamples sequences, refits the model, and reports
edge-level variability. It is useful when the population may be a mixture
of different sequence types.

```{r bootstrap}
boot <- bootstrap_lsa(fit, R = 100)
boot
transitions(boot) |> head(4)
```

`reliability_lsa()` moves from edge evidence to whole-network evidence by
repeated split-half refitting.

```{r reliability}
reliability_lsa(fit, R = 30)
```

# Start from a raw event log

Real process data often arrives as a long event log. The bundled
`group_regulation_long` data has one timestamped regulation action per
row, plus an achievement-group label.

```{r log}
head(group_regulation_long)
```

`lsa()` can recover sequences and fit the model in one call. `actor`
identifies the sequence, `action` identifies the event state, and `time`
orders events. If there is no actor column, `action` alone is valid and
the log is treated as one long sequence.

```{r log-fit}
fit_log <- lsa(group_regulation_long, actor = "Actor",
               action = "Action", time = "Time")
fit_log
```

The fitted probabilities are exposed for downstream transition-network
workflows.

```{r interop}
transition_probabilities(fit_log)
initial(fit_log)
```

# Fit groups

For group-specific models, name the grouping column. `lsa()` estimates
one model per group under the same state labels.

```{r group}
gfit <- lsa(group_regulation_long, actor = "Actor", action = "Action",
            time = "Time", group = "Achiever")
gfit
```

The reading verbs now return a leading `group` column.

```{r group-read}
transitions(gfit, significant = TRUE) |> head(6)
nodes(gfit) |> head(6)
```

# Compare groups

`compare_lsa()` tests whether groups differ by permuting group labels at
the sequence level. The result includes edge-level differences and an
omnibus comparison.

```{r compare}
cmp <- compare_lsa(gfit, R = 100, adjust = "BH")
cmp
transitions(cmp) |> head(6)
```

The default comparison plot is a back-to-back barrel display. It shows
direction, magnitude, and the permutation p-value for each edge.

```{r barrel, eval = has_ggplot2}
plot(cmp)
```

# In short

The complete analysis is a claim-to-evidence chain:

```r
fit <- lsa(engagement)
transitions(fit, significant = TRUE)
plot(fit)
plot(fit, type = "network", weights = "tna")

certainty_lsa(fit)
bootstrap_lsa(fit)
reliability_lsa(fit)

log_fit <- lsa(log_data, actor = "Actor", action = "Action", time = "Time")
group_fit <- lsa(log_data, actor = "Actor", action = "Action",
                 time = "Time", group = "Group")
compare_lsa(group_fit)
```

Descriptive claims use the fitted transition tables and plots. Edge
claims add uncertainty. Whole-network claims add reliability or
stability. Group-difference claims use permutation comparison.

```{r cleanup, include = FALSE}
options(old_options)
```
