--- 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) ```