| Title: | Complex Dynamic Systems |
|---|---|
| Description: | Performs analysis of complex dynamic systems with a focus on the temporal unfolding of patterns, changes, and state transitions in behavioral data. Supports both time series and sequence data and provides tools for the analysis and visualization of complexity, pattern identification, trends, regimes, sequence typology as well as early warning signals. |
| Authors: | Mohammed Saqr [aut], Santtu Tikka [aut, cre], Sonsoles López-Pernas [aut] |
| Maintainer: | Santtu Tikka <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.2.0 |
| Built: | 2026-05-31 07:20:33 UTC |
| Source: | https://github.com/santikka/codyna |
codyna Package.Performs analysis of complex dynamic systems with a focus on the temporal unfolding of patterns, changes, and state transitions in behavioral data. The package supports both time series and sequence data and provides tools for the analysis and visualization of complexity, pattern identification, trends, regimes, sequence typology as well as early warning signals.
Santtu Tikka and Mohammed Saqr
Useful links:
Fit a (mixed) logistic regression model to the data using sequence patterns
as predictors. The patterns are first determined using discover_patterns()
and used as predictors as specified by the user (either frequency or
presence). The user can further select the maximum number of patterns to use
and how to prioritize the patterns (frequency, support, lift, etc.).
Additional covariates and random effects can also be included in the
model. The logistic model is fitted using stats::glm() or by
lme4::glmer() in the case of a mixed model.
analyze_outcome( data, cols = tidyselect::everything(), group = NULL, outcome = "last_obs", reference, n = 10, freq = FALSE, priority = "chisq", desc = TRUE, formula = ~1, re_formula, mixed = TRUE, type = "ngram", len = 1:2, gap = 1, min_support = 0.01, min_freq = 5, start, end, contain, ... )analyze_outcome( data, cols = tidyselect::everything(), group = NULL, outcome = "last_obs", reference, n = 10, freq = FALSE, priority = "chisq", desc = TRUE, formula = ~1, re_formula, mixed = TRUE, type = "ngram", len = 1:2, gap = 1, min_support = 0.01, min_freq = 5, start, end, contain, ... )
data |
[ |
cols |
[ |
group |
[ |
outcome |
[ |
reference |
[ |
n |
[ |
freq |
[ |
priority |
[ |
desc |
[ |
formula |
[ |
re_formula |
[ |
mixed |
[ |
type |
[
|
len |
[ |
gap |
[ |
min_support |
[ |
min_freq |
[ |
start |
[ |
end |
[ |
contain |
[ |
... |
Additional arguments passed to |
Either a glm or a glmerMod object depending on whether
random effects were included.
fit <- analyze_outcome(engagement, outcome = rep(1:2, each = 500)) summary(fit)fit <- analyze_outcome(engagement, outcome = rep(1:2, each = 500)) summary(fit)
Computes dynamic complexity and other rolling window measures for univariate time series data.
complexity(data, measures = "complexity", window = 7L, align = "center")complexity(data, measures = "complexity", window = 7L, align = "center")
data |
[ |
measures |
[ |
window |
[ |
align |
[ |
The following measures can be calculated:
"complexity": Product of fluctuation and distribution measures.
"fluctuation": Root mean square of successive differences.
"distribution": Deviation from uniform distribution.
"autocorrelation": Lag-1 autocorrelation coefficient.
"max": Rolling maximum.
"min": Rolling minimum.
"variance": Rolling variance.
The option "all" computes all of the above.
A tibble with the time index, the original time-series data,
and the calculated measures.
set.seed(123) ts_data <- stats::arima.sim(list(order = c(1, 1, 0), ar = 0.6), n = 200) # Single measure comp_single <- complexity(ts_data, measures = "complexity") # Multiple measures comp_multi <- complexity(ts_data, measures = c("complexity", "variance"))set.seed(123) ts_data <- stats::arima.sim(list(order = c(1, 1, 0), ar = 0.6), n = 200) # Single measure comp_single <- complexity(ts_data, measures = "complexity") # Multiple measures comp_multi <- complexity(ts_data, measures = c("complexity", "variance"))
Converts wide format sequence data into useful formats for analysis, such as frequency table, one-Hot encoding, or edge list (graph format).
convert(data, cols = tidyselect::everything(), format = "frequency")convert(data, cols = tidyselect::everything(), format = "frequency")
data |
[ |
cols |
[ |
format |
[
|
A tibble structured according to the requested format.
convert(engagement, format = "frequency") convert(engagement, format = "onehot") convert(engagement, format = "edgelist") convert(engagement, format = "reverse")convert(engagement, format = "frequency") convert(engagement, format = "onehot") convert(engagement, format = "edgelist") convert(engagement, format = "reverse")
Detects regime changes in time series data using multiple methods including cumulative peaks, changepoint detection, variance shifts, threshold analysis, gradient changes, and entropy analysis.
detect_regimes( data, method = "smart", sensitivity = "medium", min_change, window = 10L, peak = 2, cumulative = 0.6 )detect_regimes( data, method = "smart", sensitivity = "medium", min_change, window = 10L, peak = 2, cumulative = 0.6 )
data |
[ |
method |
[
|
sensitivity |
[ |
min_change |
[ |
window |
[ |
peak |
[ |
cumulative |
[ |
An object of class regimes which is a tibble containing
the following columns:
value: Original time series data.
time: Original time points.
change: A logical vector indicating regime changes.
id: An integer regime identifier.
type: Type of change detected by the method.
magnitude: Magnitude of the change (method-specific interpretation)
confidence: Confidence in the detection
(method-specific interpretation, typically between 0 and 1, or NA)
stability: Categorical stability: "Stable", "Transitional", and
"Unstable".
score: A numeric stability score between 0 and 1.
set.seed(123) ts_data <- stats::arima.sim(list(order = c(1, 1, 0), ar = 0.6), n = 200) regimes <- detect_regimes( data = ts_data, method = "threshold", sensitivity = "medium" )set.seed(123) ts_data <- stats::arima.sim(list(order = c(1, 1, 0), ar = 0.6), n = 200) regimes <- detect_regimes( data = ts_data, method = "threshold", sensitivity = "medium" )
Eearly warning signal (EWS) detection for time series data. Both rolling
window and expanding window approaches are supported. Includes various
methods for detrending the data before analysis. For visualizing the
results, see plot.ews().
detect_warnings( data, method = "rolling", metrics = "all", window = 0.5, burnin = 0.1, demean = TRUE, detrend = "none", threshold = 2, consecutive = 2L, bandwidth, span, degree )detect_warnings( data, method = "rolling", metrics = "all", window = 0.5, burnin = 0.1, demean = TRUE, detrend = "none", threshold = 2, consecutive = 2L, bandwidth, span, degree )
data |
[ |
method |
[ |
metrics |
[
|
window |
[ |
burnin |
[ |
demean |
[ |
detrend |
[
|
threshold |
[ |
consecutive |
[ |
bandwidth |
See |
span |
See |
degree |
See |
An object of class ews containing the EWS results as a tibble.
set.seed(123) ts_data <- stats::arima.sim(list(order = c(1, 1, 0), ar = 0.6), n = 200) # Rolling window (default) ews_roll <- detect_warnings(ts_data) # Expanding window ews_exp <- detect_warnings(ts_data, method = "expanding")set.seed(123) ts_data <- stats::arima.sim(list(order = c(1, 1, 0), ar = 0.6), n = 200) # Rolling window (default) ews_roll <- detect_warnings(ts_data) # Expanding window ews_exp <- detect_warnings(ts_data, method = "expanding")
Discover various types of patterns in sequence data. Provides n-gram extraction, gapped pattern discovery, analysis of repeated patterns and targeted pattern search. Supports comparison of pattern presence between groups.
discover_patterns( data, cols = tidyselect::everything(), outcome, type = "ngram", pattern, len = 2:5, gap = 1:3, min_freq = 2, min_support = 0.01, start, end, contain )discover_patterns( data, cols = tidyselect::everything(), outcome, type = "ngram", pattern, len = 2:5, gap = 1:3, min_freq = 2, min_support = 0.01, start, end, contain )
data |
[ |
cols |
[ |
outcome |
[ |
type |
[
|
pattern |
[ |
len |
[ |
gap |
[ |
min_freq |
[ |
min_support |
[ |
start |
[ |
end |
[ |
contain |
[ |
An object of class patterns which is a tibble with the
following columns:
pattern: The discovered patterns.
length: The length of the pattern.
frequency: The number of times the pattern occurs across all sequences.
proportion: Frequency divided by the total frequency of patterns of
the same length.
count: The number of sequences that contain the pattern.
support: The proportion of sequences that contain the pattern.
lift: the support divided by the product of the supports of the
individual states of the pattern. For wildcards, the support is always 1.
In addition, if outcome is provided, additional columns giving the counts
in each outcome group, the chi-squared test statistic values (chisq),
and p-values (p_value) are included.
# N-grams ngrams <- discover_patterns(engagement, type = "ngram") # Gapped patterns gapped <- discover_patterns(engagement, type = "gapped") # Repeated patterns repeated <- discover_patterns(engagement, type = "repeated") # Custom pattern with a wildcard state custom <- discover_patterns(engagement, pattern = "Active->*")# N-grams ngrams <- discover_patterns(engagement, type = "ngram") # Gapped patterns gapped <- discover_patterns(engagement, type = "gapped") # Repeated patterns repeated <- discover_patterns(engagement, type = "repeated") # Custom pattern with a wildcard state custom <- discover_patterns(engagement, pattern = "Active->*")
Example data for complex adaptive systems perspective to behavior change research. The dataset consists of 20 individuals with 9 self-report variables (and time of response) each. For more information on the data, please see https://heinonmatti.github.io/complexity-behchange/dataset-info.html
emaema
A data.frame object.
https://github.com/heinonmatti/complexity-behchange
Students' engagement states (Active / Average / Disengaged)
throughout a whole study program. The data was generated synthetically
based on the article "The longitudinal association between engagement and
achievement varies by time, students' profiles, and achievement state:
A full program study". Used also in the tna package.
engagementengagement
An stslist object (sequence data).
doi:10.1016/j.compedu.2023.104787
Tikka S, López-Pernas S, Saqr M (2025). "tna: An R Package for Transition Network Analysis." Applied Psychological Measurement. doi:10.1177/01466216251348840
Students' regulation during collaborative learning. Students' interactions
were coded as: "adapt", "cohesion", "consensus", "coregulate", "discuss",
"emotion", "monitor", "plan", "synthesis". Used also in the tna package.
group_regulationgroup_regulation
A data.frame object.
The data was generated synthetically.
Tikka S, López-Pernas S, Saqr M (2025). "tna: An R Package for Transition Network Analysis." Applied Psychological Measurement. doi:10.1177/01466216251348840
Plot EWS Results
## S3 method for class 'ews' plot(x, ...)## S3 method for class 'ews' plot(x, ...)
x |
[ |
... |
Ignored. |
A ggplot object.
set.seed(123) ts_data <- stats::arima.sim(list(order = c(1, 1, 0), ar = 0.6), n = 200) ews_roll <- detect_warnings(ts_data) plot(ews_roll)set.seed(123) ts_data <- stats::arima.sim(list(order = c(1, 1, 0), ar = 0.6), n = 200) ews_roll <- detect_warnings(ts_data) plot(ews_roll)
Plot Discovered Patterns
## S3 method for class 'patterns' plot(x, n = 10L, prop = TRUE, group, global = TRUE, ...)## S3 method for class 'patterns' plot(x, n = 10L, prop = TRUE, group, global = TRUE, ...)
x |
[ |
n |
[ |
prop |
[ |
group |
[ |
global |
[ |
... |
Ignored. |
A ggplot object.
ngrams <- discover_patterns(engagement, type = "ngram")
plot(ngrams)
Plot Time Series Data with Detected Regime Stability
## S3 method for class 'regimes' plot(x, points = FALSE, ...)## S3 method for class 'regimes' plot(x, points = FALSE, ...)
x |
[ |
points |
[ |
... |
Ignored. |
A ggplot object.
set.seed(123) ts_data <- stats::arima.sim(list(order = c(1, 1, 0), ar = 0.6), n = 200) regimes <- detect_regimes( data = ts_data, method = "threshold", sensitivity = "medium" ) plot(regimes)set.seed(123) ts_data <- stats::arima.sim(list(order = c(1, 1, 0), ar = 0.6), n = 200) regimes <- detect_regimes( data = ts_data, method = "threshold", sensitivity = "medium" ) plot(regimes)
Print EWS Detection Results
## S3 method for class 'ews' print(x, ...)## S3 method for class 'ews' print(x, ...)
x |
[ |
... |
Additional arguments passed to the generic print method. |
x (invisibly).
set.seed(123) ts_data <- stats::arima.sim(list(order = c(1, 1, 0), ar = 0.6), n = 200) ews <- detect_warnings(ts_data) print(ews)set.seed(123) ts_data <- stats::arima.sim(list(order = c(1, 1, 0), ar = 0.6), n = 200) ews <- detect_warnings(ts_data) print(ews)
Print Discovered Patterns
## S3 method for class 'patterns' print(x, ...)## S3 method for class 'patterns' print(x, ...)
x |
[ |
... |
Additional arguments passed to the generic print method. |
x (invisibly).
ngrams <- discover_patterns(engagement, type = "ngram") print(ngrams)ngrams <- discover_patterns(engagement, type = "ngram") print(ngrams)
Print Regime Detection Results
## S3 method for class 'regimes' print(x, ...)## S3 method for class 'regimes' print(x, ...)
x |
[ |
... |
Additional arguments passed to the generic print method. |
x (invisibly).
set.seed(123) ts_data <- stats::arima.sim(list(order = c(1, 1, 0), ar = 0.6), n = 200) regimes <- detect_regimes( data = ts_data, method = "threshold", sensitivity = "medium" ) print(regimes)set.seed(123) ts_data <- stats::arima.sim(list(order = c(1, 1, 0), ar = 0.6), n = 200) regimes <- detect_regimes( data = ts_data, method = "threshold", sensitivity = "medium" ) print(regimes)
Compute Sequence Indices for Sequence Data
sequence_indices(data, cols = tidyselect::everything(), favorable, omega = 1)sequence_indices(data, cols = tidyselect::everything(), favorable, omega = 1)
data |
[ |
cols |
[ |
favorable |
[ |
omega |
[ |
A tibble containing the index values.
sequence_indices(engagement)sequence_indices(engagement)