# A tibble: 6 × 6
Actor Achiever Group Course Time Action
<int> <chr> <dbl> <chr> <dttm> <chr>
1 1 High 1 A 2025-01-01 08:27:07 cohesion
2 1 High 1 A 2025-01-01 08:35:20 consensus
3 1 High 1 A 2025-01-01 08:42:18 discuss
4 1 High 1 A 2025-01-01 08:50:00 synthesis
5 1 High 1 A 2025-01-01 08:52:25 adapt
6 1 High 1 A 2025-01-01 08:57:31 consensus

Network Estimation and Visualization with Nestimate + cograph
2026-04-01
Source:vignettes/articles/cograph-tutorial-nestimate.qmd
1 Introduction
Nestimate is a general-purpose network estimation package. It provides a unified build_network() interface that accepts raw sequence data and constructs networks using multiple methods: transition probabilities, partial correlations, regularized networks (GLASSO), co-occurrence, and more. The result is a netobject that works directly with cograph’s splot() — no conversion needed.
Beyond estimation, Nestimate provides bootstrap stability analysis, permutation-based group comparisons, higher-order network construction (HON, HYPA), and motif analysis. All output objects dispatch through splot() automatically.
2 Data
We use group_regulation_long — a long-format dataset of 9 collaborative regulation behaviors coded across student groups, with achievement group labels (High vs Low).
3 Estimating Networks
build_network() estimates a network from raw data. The method argument selects the estimator.
net <- build_network(group_regulation_long,
action = "Action", actor = "Actor", method = "relative")
netTransition Network (relative probabilities) [directed]
Weights: [0.001, 0.498] | mean: 0.116
Weight matrix:
adapt cohesion consensus coregulate discuss emotion monitor plan
adapt 0.000 0.273 0.477 0.022 0.059 0.120 0.033 0.016
cohesion 0.003 0.027 0.498 0.119 0.060 0.116 0.033 0.141
consensus 0.005 0.015 0.082 0.188 0.188 0.073 0.047 0.396
coregulate 0.016 0.036 0.135 0.023 0.274 0.172 0.086 0.239
discuss 0.071 0.048 0.321 0.084 0.195 0.106 0.022 0.012
emotion 0.002 0.325 0.320 0.034 0.102 0.077 0.036 0.100
monitor 0.011 0.056 0.159 0.058 0.375 0.091 0.018 0.216
plan 0.001 0.025 0.290 0.017 0.068 0.147 0.076 0.374
synthesis 0.235 0.034 0.466 0.044 0.063 0.071 0.012 0.075
synthesis
adapt 0.000
cohesion 0.004
consensus 0.008
coregulate 0.019
discuss 0.141
emotion 0.003
monitor 0.016
plan 0.002
synthesis 0.000
Initial probabilities:
consensus 0.214 ████████████████████████████████████████
plan 0.204 ██████████████████████████████████████
discuss 0.175 █████████████████████████████████
emotion 0.151 ████████████████████████████
monitor 0.144 ███████████████████████████
cohesion 0.060 ███████████
synthesis 0.019 ████
coregulate 0.019 ████
adapt 0.011 ██
splot() renders the netobject directly:
splot(net)One line builds different network types:
build_network(group_regulation_long, action = "Action", actor = "Actor", method = "frequency")
build_network(group_regulation_long, action = "Action", actor = "Actor", method = "attention")
build_network(group_regulation_long, action = "Action", actor = "Actor", method = "co_occurrence")
build_network(group_regulation_long, action = "Action", actor = "Actor", method = "glasso")
build_network(group_regulation, method = "pcor")4 Bootstrap Stability
bootstrap_network() resamples the data and refits the model at each iteration, identifying which edges are stable and which are sampling artifacts.
set.seed(265)
boot <- bootstrap_network(net, iter = 1000)
boot Edge Mean 95% CI p
-----------------------------------------------
cohesion → consensus 0.498 [0.474, 0.521] ***
adapt → consensus 0.478 [0.430, 0.523] ***
synthesis → consensus 0.466 [0.427, 0.507] ***
consensus → plan 0.396 [0.383, 0.407] ***
monitor → discuss 0.375 [0.351, 0.401] ***
... and 46 more significant edges
Bootstrap Network [Transition Network (relative) | directed]
Iterations : 1000 | Nodes : 9
Edges : 47 significant / 71 total
CI : 95% | Inference: stability | CR [0.75, 1.25]
4.1 Network plots
Significant edges appear solid; non-significant edges appear dashed grey.
splot(boot)
splot(boot, display = "significant")
splot(boot, show_stars = TRUE)
splot(boot, show_ci = TRUE)4.2 Forest plots
Forest plots show edge weights and confidence intervals in a compact format. Three layouts are available:
plot_bootstrap_forest(boot)
plot_bootstrap_forest(boot, layout = "circular")
plot_bootstrap_forest(boot, layout = "grouped")5 Group Networks
Pass group = to build_network() to estimate a separate network per group. splot() renders all groups in an automatic grid.
grp_net <- build_network(group_regulation_long, method = "relative",
action = "Action", actor = "Actor", time = "Time", group = "Achiever")
names(grp_net)[1] "High" "Low"
splot(grp_net)common_scale = TRUE (default) makes edge widths directly comparable across panels:
splot(grp_net, common_scale = FALSE)6 Permutation Testing
permutation_test() tests whether each edge differs significantly between two groups.
set.seed(265)
perm <- Nestimate::permutation_test(grp_net$High, grp_net$Low, iter = 1000)
permPermutation Test:Transition Network (relative probabilities) [directed]
Iterations: 1000 | Alpha: 0.05
Nodes: 9 | Edges tested: 78 | Significant: 42
splot(perm)
splot(perm, show_nonsig = TRUE)
splot(perm, show_stars = TRUE, show_effect = TRUE)7 Motifs
Nestimate objects work directly with cograph’s motif analysis. motifs() counts MAN triad types; subgraphs() identifies specific node triples.
mot <- cograph::motifs(net, significance = TRUE, n_perm = 100, seed = 42)
motMotif Census
Level: aggregate | States: 9 | Pattern: triangle
Significance: permutation (n_perm=100)
Type distribution:
210 300
1 1
Top 2 results:
type count expected z p sig
300 77 6.3 21.25 0.0000 TRUE
210 7 21.6 -2.30 0.0216 TRUE
plot(mot, type = "types")
plot(mot, type = "significance")Named subgraphs — which states form which patterns:
sg <- cograph::subgraphs(net, significance = FALSE, top = 10)
sgNULL
plot(mot, type = "patterns")8 Higher-Order Networks
When first-order Markov models are insufficient, Nestimate detects higher-order sequential dependencies.
8.1 HON
build_hon() identifies transitions where prior context changes the outgoing distribution:
hon <- build_hon(net)
honHigher-Order Network (HON)
Nodes: 719 (9 first-order states)
Edges: 2855
Max order: 5 (requested 5)
Min freq: 1
Trajectories: 2000
8.2 HYPA
build_hypa() detects paths that occur significantly more or less often than expected:
hypa <- build_hypa(net)
table(hypa$scores$anomaly)
normal over under
1921 546 117
over <- hypa$scores[hypa$scores$anomaly == "over", ]
head(over[order(-over$ratio), c("path", "ratio", "observed", "expected")], 8) path ratio observed
114 synthesis -> adapt -> monitor -> discuss 76.45996 7
386 plan -> consensus -> adapt -> consensus 57.45136 5
806 plan -> consensus -> synthesis -> adapt 48.61269 5
1457 monitor -> discuss -> plan -> consensus 39.49781 5
2530 discuss -> synthesis -> coregulate -> consensus 38.46743 5
2535 discuss -> synthesis -> coregulate -> plan 38.46743 6
822 consensus -> coregulate -> adapt -> cohesion 36.11228 6
2492 discuss -> synthesis -> cohesion -> consensus 35.18896 7
expected
114 0.09155119
386 0.08703014
806 0.10285380
1457 0.12658930
2530 0.12998008
2535 0.15597610
822 0.16614845
2492 0.19892604
8.3 Simplicial visualization
plot_simplicial(net, max_pathways = 6, title = "Higher-Order Pathways")
plot_simplicial(net, max_pathways = 9, dismantled = TRUE, ncol = 3)9 The Dispatch Chain
Every Nestimate object routes through splot():
All standard splot() arguments (layout, node_fill, edge_color, title, etc.) work with every object type.
References
Saqr, M., López-Pernas, S., Törmänen, T., Kaliisa, R., Misiejuk, K., & Tikka, S. (2025). Transition Network Analysis: A Novel Framework for Modeling, Visualizing, and Identifying the Temporal Patterns of Learners and Learning Processes. In Proceedings of the 15th International Learning Analytics and Knowledge Conference (LAK ’25) (pp. 351–361). ACM. https://doi.org/10.1145/3706468.3706513
Tikka, S., López-Pernas, S., & Saqr, M. (2025). tna: An R Package for Transition Network Analysis. Applied Psychological Measurement. https://doi.org/10.1177/01466216251348840
Nestimate: https://github.com/mohsaqr/Nestimate