build_hypa() now defaults to p_adjust = "none", following LaRock et al.
(2020), who classify paths against the threshold alpha without
multiple-testing correction. Pass p_adjust = "BH" for the previous
behaviour.build_hypa() used a miscalibrated null model. The propensity matrix was
s_out * s_in restricted to observed paths, normalised over the whole
graph and never refitted, so expected counts did not preserve node
strengths: high-strength contexts were systematically under-represented and
rare contexts over-represented, and memoryless (first-order Markov) data
produced dozens of anomalies. Xi is now built on every possible De Bruijn
edge (an observed k-gram continued by an observed first-order transition)
and refitted until expected in- and out-strengths match the observed ones,
following LaRock et al. (2020) and the reference tlarock/hypa code.
build_hypa() fits the propensity matrix by continuous iterative
proportional fitting instead of a rounded, keep-best sweep. Expected counts
now preserve every De Bruijn node's in- and out-strength to numerical
precision (order 2 equals the first-order Markov expectation exactly), and
converged is reported only when the tolerance is met; otherwise a warning
of class nestimate_hypa_no_converge is raised. Stalled fits were
previously reported as converged. Expected counts can differ from the
original Python implementation, which rounds inside every sweep, by a few
thousandths.
build_hypa() validates its input: min_count must be a single whole
number, alpha a single number in (0, 0.5) and order free of duplicates
(duplicates previously doubled every row and anomaly). Internal missing
states now split a trajectory instead of becoming a state called "NA", and
labels containing the internal separators \x01/\x02 raise an error of
class nestimate_hypa_bad_label.
build_hypa() now uses the over-representation rule of LaRock et al.
(2020): a path is over-represented when its HYPA score P(X <= f) exceeds
1 - alpha, so p_over is the strict tail P(X > f) = 1 - p_under
(previously the inclusive P(X >= f)).
build_hypa() can now flag paths that never or rarely occur as
under-represented. min_count gates over-representation on the observed
count and under-representation on the expected count; previously a path
observed fewer than min_count times could never be a deficit.
Possible but unobserved paths are now scored (observed = 0), so
$scores and n_edges contain more rows. At order 2 the expected count
reduces to the first-order Markov expectation.
print.q_analysis() reported the fragmentation point from the highest q
down, because q_vector is stored from the highest q; it now reports the
lowest q with more than one component (e.g. q = 2, not q = 4, for a clique
complex whose maximal simplices meet only in triangles).
verify_simplicial() accepts a network object (netobject, tna,
cograph_network, net_hon) as well as a matrix, as build_simplicial()
does.build_mcml and
plot_state_frequencies had been named after a print() method, and
their usage now lists the function before its methods.... entry states what each method does with extra
arguments: methods that reject them say so, plot.net_bayes() names
cograph::splot(), and the rest say they are ignored.compare_networks: the ... and labels entries no longer repeat;
net_edge_betweenness and net_pruning_details no longer list a
non-existent class.mgm estimator rejects scale = FALSE with a classed error
(nestimate_mgm_unscaled); this started in 0.9.23 and was not listed
there. Missing values are handled pairwise, now passed explicitly.passage_time(), a manual multinom re-computation) and unused reference
helpers moved to the local suite; section headers that claimed
equivalence tests are renamed. New tests: mgm on data with missing values,
and the scale = FALSE error.mgm and ising estimators delegate to psychnets::mgm_fit() and
psychnets::ising_fit() (glmnet engine), joining cor, pcor and glasso.
Results are unchanged: identical to the former in-package code (max absolute
difference 0 for Ising over 180 configurations, 5.6e-17 for MGM over 48).
Nestimate keeps type detection, input validation and the result fields. The
Ising result no longer carries the unused asymm_weights and
lambda_selected fields. The unused internal moderated-MGM code is removed.print(), summary(), plot(),
format() and as.data.frame() methods are documented on the page of the
function that creates their object (?nct covers print.net_nct() and
summary.net_nct()), as is compare_model()'s netobject_group method.
286 help pages become 139; ?print.net_nct still opens the right page.compare_model() and as_netdifference() have examples.build_network(method = "mgm") no longer fails on data with missing values
("number of observations in y not equal to the number of rows of x").glm()) and naive-loop reference implementations are no longer shipped.boot_glasso(), nct(),
permutation_diagnostics(), build_gimme()) and ?sequence_plot draws
fewer figures.summary() of a predict_links() result reports NA scores for a method
with no predictions (every possible link already exists). It returned
NaN / -Inf / Inf with one warning per column.R CMD check. 31 pages
had all of it inside \donttest{} or \dontrun{}; fast examples are
unwrapped, and slow ones (nct(), permutation_diagnostics(),
entropy_bayes()) run live with fewer iterations.predict_links() family of examples uses fixed data that leaves links
to predict, and the loading_stability() / as_networks() examples use items
with real two-factor structure, so neither emits warnings.cograph-tutorial-nestimate article was a 47.8 MB page (300 dpi
figures inlined as base64); it is now about 70 KB with figures as separate
files. The README no longer lists outdated imports.https://pak.dynasite.org/Nestimate/
(DESCRIPTION URL, _pkgdown.yml, README links). saqr.me/Nestimate was a
stale copy. The README lists the permutation-nested-data and
compare-networks articles.state_colors(),
set_state_colors(), composites(), item_loadings()) were missing from the
reference index, which had failed every site build since 0.9.10. The
compare-networks and permutation-nested-data articles now publish.compare_networks() gains actor =, passed to the permutation backend:
whole actors are reassigned between the networks, the printed header names
the actor column, and global_differences() gains the rows ICC,
Design effect (edges) and Design effect (M) (category "Nesting").
Requires test = "permutation" (error class
nestimate_compare_actor_needs_permutation).permutation(),
permutation_diagnostics()) and 0.9.15 (bootstrap_network()) is renamed
from block to actor, the column identifying whose sequences they are:
the same vocabulary as build_network(actor = ). Results carry actor
and n_actors; diagnostic columns use _sequence (sequences reassigned)
and _actor (actors reassigned), e.g. p_global_sequence /
p_global_actor; conditions are nestimate_bad_actor,
nestimate_actor_missing, nestimate_actor_misaligned,
nestimate_actor_unsupported and nestimate_few_actors. The printout
reads Actor: Group (200 actors) and Nesting in Group: ICC = ....
Neither name was ever on CRAN.build_network(): columns named in metadata_cols (or left out of
state_cols) are no longer read as sequence positions in wide data. They
were moved to $metadata only after estimation, so their values became
states and created spurious transitions, in single and grouped networks.
For cor, pcor, glasso, ising and mgm, declared metadata columns
are no longer entered as variables.
An ICC that cannot be estimated (one block, or no variation) is reported
as not estimable instead of NaN [NA, NA] by permutation(),
bootstrap_network() and permutation_diagnostics().
bootstrap_network() gains block =, the column identifying the unit
that sequences are nested in. Whole units are resampled with replacement,
keeping their sequences together (cluster bootstrap, top level only;
Davison & Hinkley, 1997; Field & Welsh, 2007). The result reports the ICC
(Shrout & Fleiss, 1979) and the design effect (Kish, 1965) for the edges,
printed under the bootstrap summary and returned as clustering and
clustering_edges. With one sequence per unit it reproduces the ordinary
bootstrap exactly. Transition networks only.group_regulation_long, every summary table and
all eight plot views with a short reading of each.permutation() gains block =, the column identifying the unit that
sequences are nested in (sessions in students, students in teams). Whole
units are reassigned between the groups; units with sequences in both
groups, as in repeated-measures designs, have their sequences reassigned
within the unit; mixed designs combine the two (Good, 2005; Anderson &
ter Braak, 2003). Supported for transition networks (relative,
frequency, co_occurrence); association networks raise
nestimate_block_unsupported. A warning of class nestimate_few_blocks
is raised when no p-value could fall below alpha.
With block, permutation() reports the nesting effect: the intraclass
correlation (Shrout & Fleiss, 1979) with a jackknife 95% interval, and the
design effect (Kish, 1965), the blocked over the unblocked null variance,
for the edges and the global statistic M.
permutation_diagnostics(x, block =) runs the ordinary and the blocked
test on the same data and returns them side by side as a tidy data frame,
one row per pair or, with level = "edges", per edge.
print() of a net_permutation shows the global test (M and S, with
p-values) and, with block, the ICC and design effects. A grouped result
prints every pair in full.
The permutation() help page is reorganised into sections: what is
tested, nested data and block, ICC and design effect, reading the
printed output.
Building a transition network from a single long sequence now raises a
message instead of a warning; running bootstrap_network() or
permutation() on such a network still warns. Both carry the class
nestimate_single_sequence.
\% in markdown roxygen silently cut the rest of a line from the help
pages of certainty(), build_gimme(), build_mcml() and
sequence_plot(); the text is restored.
Missing space in the permutation() print header.
set_state_colors(x, colors) attaches a palette to a netobject,
netobject_group, mcml or htna, and every figure drawn from that object
then uses it -- sequence_plot(), distribution_plot(),
plot_state_frequencies() and cograph::splot(). The cograph half goes
through the documented meta$splot producer contract (defaults$node_fill,
stamped in node order), so splot(net) needs no arguments and renders
byte-identically to splot(net, node_fill = ...). A state_colors(x) <-
replacement form is also available.
state_colors(x) reads the resolved palette back as a tidy data.frame: one
row per key, with state, color and source ("set" or "default"). It
is what the figures actually draw, not just what was passed in.
States a named palette does not mention are now dealt the Okabe-Ito colours
the palette has not used, one each, instead of taking their positional
slot. Pinning plan = "#0072B2" no longer leaves another state defaulting to
that same blue. Affects the named form only; an unnamed state_colors and
the all-default palette are unchanged.
An attached palette resolves once, in the object's own key order, so
every figure drawn from it colours a state identically. Previously only the
colours you set were carried and each figure dealt the remaining defaults in
its own sort order -- plot_state_frequencies() sorts states by frequency
and sequence_plot() alphabetically, so one state could come out amber in
one figure and black in the other.
In-tile labels in plot_state_frequencies() take whichever ink (dark or
white) has the higher WCAG contrast ratio against the tile, instead of one
fixed grey. A percentage on a dark tile -- black, navy, dark wine -- is now
readable, whether the colour came from the default palette or from a palette
you set.
state_colors no longer has to match the figure exactly. Names the
plot does not draw are dropped with a message() naming them, so one
project-wide palette -- states from a wider coding scheme, clusters a given
call merged away -- can be handed to every plot and each takes the keys that
apply to it. 0.9.10 raised an error instead, which made a shared palette
unusable.state_colors accepts a named vector everywhere sequence_plot(),
distribution_plot() and plot_state_frequencies() draw, and the names are
a lookup rather than a positional list: only the keys you name are
overridden, every other key keeps its default, and the vector may be shorter
than the number of states. An unnamed vector is still positional, unchanged.
For an mcml, that lookup covers the whole multichannel figure, not only
the states. A cluster name colours its Summary band, its channel strip and
its faded band in the other panels; a group merged by combine = is named
by its label (the list name, or "A + B"); rest_label is a key too. So
sequence_plot(fit, combine = list(Task = c("Cognitive", "Regulation")), state_colors = c(Task = "#0072B2")) recolours the combined cluster and
leaves the rest of the palette alone. Previously the cluster and combined
keys were drawn from a fixed internal palette with no way to set them.
A state_colors name that matches no key in the figure is now an error
naming the available keys, instead of being silently ignored.
build_mcml() gains combine = and expand =. On new input they change
the partition before estimation, in any clusters form and for every input
type: build_mcml(data, clusters = cl, combine = c("A", "B")) equals a build
with A and B merged in cl (the merged cluster lists its states in
cluster-name order). On an existing mcml they re-partition it:
build_mcml(mc, combine =) merges clusters, build_mcml(mc, expand =)
splits clusters into one cluster per state, and build_mcml(mc, clusters =)
applies a new partition. The
model (macro network, within-cluster networks, sequences) is re-estimated
from the sequences the mcml carries, with its original type, method
and directed. With the partition unchanged the result equals the input;
expand = "all" reproduces the node-level transition network of the same
type. Raises nestimate_mcml_no_sequences for an mcml built from a
matrix or an edge list (which keeps only within-cluster edges), and errors
when sequence-shaping arguments (trim, exclude, end, labels,
actor, ...) are passed with a re-partition, since the carried sequences
already reflect them.session_ids() names the session behind every sequence of a network built
from long data, and of a build_mmm() or build_clusters() fit on such a
network. It returns one row per sequence in model order: sequence, the
actor and session columns under their own names, session_label, and,
for a fit, cluster (plus posterior for a mixture). The fit's assignments
can then be joined to the input by those columns instead of parsing the
"actor | session" label, which breaks when an id contains " | ". Raises
nestimate_no_session_ids for wide-data input or for fits made before this
version, and nestimate_session_ids_misaligned when the metadata and the
sequences differ in number.item_loadings() returns the tidy item-diagnostic table of a
build_mcml_pc() fit (node, cluster, loading, weight, sign, max_cross,
cross_cluster, misfit); misfit = TRUE/FALSE filters it.composites() returns the per-respondent cluster scores of a
build_mcml_pc() fit: one row per input row (input order and row names,
NA where all of a cluster's items are missing) and one column per
cluster. Raises nestimate_no_composites for the descriptive aggregations
("average", "escoufier", "cancor"), which form no score.sequence_plot() on an mcml gains combine =: named clusters are merged
into one channel (a character vector for one group, a list for several;
list names label the merged channels, default "A + B"). The merged group
acts as one cluster across the figure (one panel, one Summary key, one
faded band) and can itself be opened with expand =.
sequence_plot() on an mcml gains rest = c("clusters", "pooled", "none"): how a cluster's panel shows the time spent in other clusters (one
faded band per cluster, one pooled grey band, or blank, leaving
only the panel's own states). Applies to the carpet and distribution views.
rest_label = (default "Other states") sets the legend text: the pooled
band takes it as is, per-cluster bands read "Social (Other states)". This
replaces the former "(elsewhere)" wording.
sequence_plot() on an mcml now honours na = in the distribution view:
na = FALSE drops the NA (ended) band and shows each time point as shares
of the sequences still running, as distribution_plot() already did.
macro_network() accepts an mcml_pc fit and returns its cluster-level
network; expand = on an mcml_pc raises nestimate_no_expand, and
method = or ... error (the estimator is set in build_mcml_pc()).
sequence_plot() errors when combine, expand, rest or rest_label
is passed for input that is not an mcml, instead of ignoring them.
print.mcml_pc() and its build-time warnings name item_loadings()
instead of pointing at $loadings.
prepare() (and so build_network() on long data) keeps the session
column(s) in the per-sequence metadata under their own names, and returns
the metadata explicitly in sequence row order (it was assembled with
merge(sort = FALSE), whose order is unspecified).
build_mmm() and build_clusters() keep the input network's $metadata
(restricted to the fitted rows when build_mmm() drops sequences with
missing covariates).
sequence_plot() on an mcml with type = "heatmap"/"index" and
expand = drew the other-cluster wash as blank cells: the wash was keyed by
the Summary keys, which are states once a cluster is expanded. It is now
keyed by cluster.sequence_plot() on an mcml with type = "distribution" and expand =
no longer fails with "subscript out of bounds" in the default
(normalize = FALSE) view. The Summary band now opens the expanded
cluster into its states, and the other panels draw it as one faded
"<cluster> (<rest_label>)" band.sequence_plot() on an mcml with a single channel (one cluster, or every
cluster merged by combine) no longer fails in the carpet view with
"replacement has 1 row, data has 0".sequence_plot() on an mcml: with expand =, each cluster's faded band
in the other panels now has its own colour (expanded clusters all shared
one).macro_network() returns the macro (cluster-level) network of an mcml
with one or more named clusters expanded back into their member states and
every other cluster left collapsed — a network at mixed resolution. It
re-counts from the recoded sequence data rather than splitting the k x k
aggregate, which cannot be disaggregated; a matrix-derived mcml raises
nestimate_no_expand_source. $node_groups maps each expanded state back
to its parent cluster, so the result plots grouped.extract_pathways() cuts a long event log into pathways and returns one
row per pathway. Three cuts via type =: "unit" (one pathway per group),
"segments" (one per contiguous run), "anchored" (spans around an anchor
event). resolve = appends a resolution label as the closing state.outcome_model() regresses a unit-level outcome on sequence or network
predictors — pattern indicators, simplicial_features() output, or any
numeric covariate — with family auto-detection, an optional lme4 random
intercept, select = "split" hold-out selection, BH-corrected p-values,
confidence intervals and odds ratios. effects_table() is the tidy
accessor; summary() returns the same table.simplicial_features() returns topological summaries of one or many
networks as a tidy data.frame, one row per network per threshold, ready to
use as regression predictors. Accepts a netobject, netobject_group,
mcml, a square weight matrix, or a named list of any of these.build_mcml() gains the exclude, trim, end and end_by sequence
arguments, applied in that fixed order.as_tna() is now a generic. as_tna.mcml(expand =) delegates to
macro_network() for the macro layer only; per-cluster layers are
untouched. An as_tna.default() covers everything else.sequence_plot() and its mcml method gain
panel = c("both", "summary", "channels").frequencies(format = "frequency") returned zero rows for any long-format
data whose id column was not integer-valued. The sequence key was coerced
with as.integer() before the merge, turning every character id into NA;
the merge then matched nothing and failed silently. Sequence keys are now
aligned in their character form.sequence_plot() on an mcml errored whenever a singleton cluster was
named after its own state: the shared fill scale built its levels with
factor(levels = c(states, clusters)), and duplicate levels are an error.
Levels and values are now de-duplicated.as.data.frame() methods for net_hypergraph_transduction and
net_hypergraph_cluster placed what in the generic's row.names slot,
so as.data.frame(x, "scores") bound "scores" to row.names. The
generic's arguments now come first and row.names is honoured
(R CMD check "S3 generic/method consistency").build_reference_index() failed. The S3 Methods section now
wildcards as.data.frame. alongside print., summary. and plot., so a
future result class with the house-standard accessor cannot repeat it.netobject, netobject_group, tna,
group_tna, mcml, cograph_network, matrices, or a list of them) in one
object. summary() returns the tidy one-row-per-pair overview, as every
other Nestimate summary() does; the full tables are their own verbs:
edge_differences(), node_differences(), global_differences(),
network_metrics(), each with a pair column. All pairs by default, or
every network against one reference =.NA, never Inf/NaN); every cell is kept, absent
edges appear at weight 0; higher (colour) and status (shape) columns
drive the plots.plot(x) draws one view per call, selected with type = (the package-wide
argument name; what = is accepted as an alias): "networks" (default;
each network drawn once via cograph::splot()), "difference" (the signed
difference network of each pair), "edges" (ranked dumbbell), "nodes",
"global", "heatmap", "scatter", and "inference" (a forest of the
edge differences on the difference scale, with credible intervals when the
Bayesian backend ran, a filled marker for a significant edge and the
p-value in a right-hand column; it raises
nestimate_compare_no_test when test = "none"). One sign-to-colour
contract (#4A6FE3 = first/reference higher, #D33F6A = second higher)
backed by line type and marker shape; the heatmap scale follows the data.plot(x, combined = FALSE) splits a multi-pair view into a named list of
single-pair plots (one per pair) instead of facetting them into one figure,
matching the combined argument of plot.net_reliability(),
plot.simplicial_complex() and friends. The base-graphics views draw one
panel per page.test = "permutation", "bayes"
(with an optional rope), "bootstrap", combinable. Non-significant
results are faded, never deleted.permutation() gains a $global data frame with NCT-style M (sum of
absolute differences) and S (largest absolute difference) statistics and
their permutation p-values, computed from the same null.compare_model() is unchanged and will be soft-deprecated once
compare_networks() has been through one release.build_hypergraph() promotes a network's k-cliques (k >= 3) to hyperedges,
following Burgio, Matamalas, Gomez and Arenas (2020); underlying pairwise
edges are retained. clique_expansion() projects a hypergraph back to a
pairwise network in one tcrossprod() call, closing the
event data -> bipartite_groups() -> hypergraph -> network cycle.hypergraph_measures() returns the structural-statistics suite (Lee, Choe
and Shin 2024); an empty hypergraph returns trivial zeros rather than
erroring. hypergraph_centrality() computes Benson's (2019) three
eigenvector centralities.hypergraph_laplacian() computes the normalized Laplacian, either the
Zhou, Huang and Scholkopf (2006) form on the binary incidence pattern or
the Hayashi, Aksoy, Park and Park (2020) weighted form. Built on it:
hypergraph_cluster() (spectral clustering) and
hypergraph_transduction() (semi-supervised label propagation), each with
print, summary, plot and as.data.frame() methods.tna-parity release: sequence-side gaps against tna::build_model() and
tna::prepare_data() closed.
build_network(method = "ngram") (params n_gram, default 2),
"gap" (params max_gap, default 1) and "reverse" (params weighted)
mirror the tna types "n-gram", "gap" and "reverse". Weights are
numerically identical to tna on shared inputs (tested). All three accept
wide or long input, start/end boundary markers, group = dispatch and
scaling = "normalize" for row probabilities."n-gram" / "n_gram" -> "ngram", "co-occurrence" ->
"co_occurrence".prepare() and build_network() gain timezone = "UTC" (Olson name).
Naive timestamps are interpreted in that zone; ISO-8601 Z/UTC/GMT
markers and numeric offsets (+0200, +02:00) are converted from their
offset. Parsing no longer depends on the machine's local time zone....Z timestamps parsed to NA (the marker was stripped before
matching), offsets were silently ignored, and wall-clock readings inside a
DST gap could turn into spurious session boundaries. Unparsable values now
raise an error instead of becoming session breaks.Delegation release: Nestimate stops owning psychometric-network math and
delegates it to its two clean-room home packages, psychnets (cross-sectional)
and idiographic (temporal). No public API changes: every signature, default,
return shape, and — verified against frozen pre-delegation baselines — every
number is preserved.
cor, pcor, and glasso estimators keep Nestimate's input layer,
validation, and return contract; the math now runs in
psychnets::cor_network() / pcor_network() / ebic_glasso(). Verified
field-complete against the frozen baseline: cor exact, pcor within
5.6e-17, glasso exact on weights, precision, selected lambda, and the
EBIC path (including penalize.diagonal and refit branches).nct() delegates its inner EBIC-glasso solve; the NCT-specific nearPD
symmetrization stays local. Seeded runs: networks and p-values exact.boot_glasso() and permutation() (glasso branch) delegate the
per-resample solve via psychnets::ebic_glasso(lambda_path = ), keeping
the fixed-path-across-resamples semantics. Seeded permutation() is
byte-identical; boot_glasso() is identical except wall-clock timing.glasso_pure.R) and its EBIC helpers
are deleted; psychnets owns that math now.ising and mgm estimators remain local for now (their delegation
needs psychnets to expose per-node lambda selection and a scale
passthrough) and are unchanged.build_mlvar() keeps its signature, S3 methods, and return object; the
lmer estimation pipeline now runs in idiographic::fit_mlvar(). Verified
identical at tolerance 0 (object, class, print, summary) across
lag/standardize/day/beep configurations, and against mlVAR::mlVAR() at
8.8e-16 over 954 checks.build_mlvar() now warns before returning the zero matrix; it
previously returned it silently. Numbers are unchanged.build_gimme() delegates its whole search to idiographic::fit_gimme().
This is the one delegation that changes results: idiographic's search
reproduces the upstream gimme package (>= 10.0) exactly, which
Nestimate's own search did not — the individual-level path search in
particular under-detected person-specific paths relative to upstream.
Group-level results are typically unchanged; individual-level path sets
can grow. The signature and the net_gimme field contract are unchanged
(the object gains idiographic's netobject fields and now renders directly
with cograph); print/summary/plot dispatch to idiographic's
methods. Treat pre-0.9.0 build_gimme() individual-level results as
superseded.Bug-fix release. 0.8.4 was published on r-universe but never reached CRAN.
plot() on net_entropy_bayes and net_sequence_comparison results no
longer fails where the graphics device cannot represent the arrow glyph.
Edge labels and the comparison subtitle previously used U+2192/U+2190,
which a non-UTF-8 locale cannot convert; the graphics engine raised an error
(conversion failure ... in 'mbcsToSbcs') rather than substituting a
character, so the plot could not be drawn at all. Both now use the ASCII
arrow notation (A -> B) already used by the higher-order network verbs.
Console output is unaffected.
plot() on net_entropy_bayes results no longer emits a deprecation warning
under ggplot2 4.0, which removed geom_errorbarh().
entropy_network() now renders with its intended transition-network styling
on cograph 2.4.4, the current CRAN version. The object states its full style
through cograph's meta$splot producer contract instead of relying on
cograph recognising the "entropy" method name, so no cograph update is
required. Output is identical under cograph 2.4.4 and 2.4.5.print() and plot() examples for the MMM clustering attribute now
reach it through build_network(), matching the 0.8.4 change that made
cluster_mmm() return the fitted net_mmm object.transition_entropy() — entropy rate H (stationary distribution from
the eigendecomposition at lambda = 1), stationary entropy, redundancy,
per-state branching entropies, all with the normalized (scale-free)
variants; print/summary/plot and netobject_group dispatch.entropy_network() — the exact edge-level decomposition of H: each
edge carries its term pi_i P_ij log(1/P_ij); weights sum to H. Displays
the summands of the entropy-rate equation — no new quantity is
estimated. scaling = "share" relabels edges as percentages of H
(sum = 100). Additional weights: "surprisal" (optionally
scaling = "chance") and "production" (irreversibility). The result
is a regular netobject that inherits its source network's styling and
ships an entropy house style via cograph's meta$splot producer
contract, which states the styling outright rather than relying on
cograph recognising the method name (cograph >= 2.4.4).entropy_trajectory() — sliding-window entropy over the transition
stream (the windowed design of Krejtz et al. 2025): tidy per-window
table, per-group trajectories, loess-trend plot; the per-window
estimator weights rows by observed occupancy (robust to non-ergodic
window fragments).entropy_bayes() — Dirichlet-posterior estimation: credible intervals
for H, per-state entropies, and per-edge contributions; edges flagged
credible when their share of H credibly exceeds min_share; $model
holds the pruned stable entropy network.cluster_mmm() now returns the fitted net_mmm clustering object, retaining
assignments, posterior probabilities, mixing proportions, fit criteria, and
fitted component models. Network materialization remains the responsibility
of build_network(fit) or the one-step
cluster_network(..., cluster_by = "mmm") workflow.as_htna() gains a net_mmm method. An MMM fit created from an HTNA model is
materialized into an htna_group without rerunning the MMM fit, while the
original actor partition and clustering diagnostics are preserved.as_htna() still rebuilds one full node-level network from the original
source, preserving every between-cluster transition, and now completes the
canonical HTNA contract. Its result inherits from htna, netobject, and
cograph_network; stores character actor labels in $node_groups$group, a
factor in $nodes$groups, and actor order in $actor_levels; and retains
actor-order metadata on $node_groups for lossless partition round trips,
plus the legacy $nodes$cluster and "cluster_members" metadata.prepare() now identifies sessions from the observed combinations of the
actor and session columns instead of base::interaction(). Three
defects are fixed:
interaction() codes a combination over the
marginal level space, which exceeds .Machine$integer.max once both
columns pass 46,341 distinct values. The resulting NAs were pasted into
the literal string "NA", merging unrelated events into one pseudo-session.
On 50,000 actor-session pairs this silently discarded 14% of sessions and
manufactured transitions that no input sequence contained, including
self-loops on terminal states." | " before being
used as a grouping and metadata merge key, so ("a | b", "c") and
("a", "b | c") collapsed into a single session. Grouping now keys on the
original columns; the readable label is display-only and is exposed as
.session_label in meta_data.Group numbering reproduces interaction()'s ordering, so prepared row order
and finite same-seed bootstrap results are unchanged.
time_threshold = FALSE switches session-interval splitting off, so each
actor (or actor-session) forms a single sequence regardless of gap length.
Accepted by prepare(), build_network() and build_mcml().
interaction() for row-order compatibility.Distance clustering and mixed-Markov clustering now preserve HTNA inputs.
build_clusters() and cluster_mmm() carry the node-to-actor partition into
network materialization, while cluster_network() returns an htna_group
directly. Every child remains an htna object with
$node_groups, $nodes$groups, and $actor_levels; clustering assignments,
posterior probabilities, fit diagnostics, and other outer attributes remain
attached.
Added extensive randomized equivalence coverage across distance clustering, mixed-Markov clustering, all transition-network estimators, actor-absent clusters, and HTNA-versus-plain input paths.
The Bayesian verbs get their own reference section, placed directly after
Network Estimation: certainty(), bayes_compare(), subtract_networks()
and as_netdifference(). They were previously buried in a fourteen-entry
"Bootstrap & Inference" list. bootstrap_network() now points at
certainty() as its closed-form counterpart, and permutation() points at
bayes_compare() as its Bayesian complement, so each pair is reachable from
either side.
frequencies() is no longer marked \keyword{internal}. The topic page and
the exported function share a roxygen topic name, so the keyword from the
topic block leaked onto the function's own help page even though the function
is exported (and called by the \pkg{htna} package). cluster_data() keeps its
internal keyword: it is a deprecated alias for build_clusters() and is meant
to stay out of the index.
Dropped the utils help page, which documented no exported object. The
@importFrom directives it carried are retained.
audit_codex/ is no longer tracked; it holds generated audit artifacts.
Suggests: cograph (>= 2.4.4). The netdifference verbs added in 0.7.8 need
cograph 2.4.x: CRAN's cograph 2.3.6 contains no netdifference support, so
cograph::plot_difference() does not exist there and cograph::splot() on a
netdifference falls through to the plain netobject renderer and silently
draws an unsigned network. Nestimate must not be submitted to CRAN before
cograph 2.4.4 is available there.subtract_networks() / as_netdifference() — verbs for the difference
between two networks. subtract_networks(x, y) returns the edge-wise
difference as a netdifference object; as_netdifference() promotes an
existing comparison result to the same class — a bayes_compare() result,
or a netdifference, which passes through; anything else errors — so a
difference computed by any route prints the same way. Adds
print.netdifference.
bayes_compare() accepts two net_edge_betweenness() objects (source
method "relative" only). Edge betweenness is recomputed on every
posterior draw, giving the Bayesian analogue of permutation()'s
edge-betweenness dispatch, with posterior mean betweenness matrices and
the plug-in observed_diff.
permutation() gains a measures argument for centrality permutation
tests, matching the tna package's dispatch.
bayes_compare()'s probability-of-direction column is renamed pd ->
p_difference in the summary() frame, and the result now carries class
c("net_bayes", "netdifference", "net_permutation") so it dispatches to
the difference verbs as well as the permutation ones.
Non-ASCII characters normalized across R sources and man pages.
centrality_stability() no longer errors with
"missing value where TRUE/FALSE needed" when a requested measure is
undefined on the network (e.g. Diffusion is NaN on a small cyclic
net): sd() returned NA, which poisoned if (!any(keep)). Such
measures now drop like zero-variance ones.
centrality_stability()'s default measures is restored to
c("InStrength", "OutStrength", "Betweenness"). 0.7.7 had swapped
OutStrength for Diffusion, which broke the \pkg{htna} package: it calls
centrality_stability() with no measures and compares the result
against its own explicit trio. centrality() / net_centrality() keep
the Diffusion default; only centrality_stability() reverts.
Suggests: cograph relaxed from (>= 2.4.4) to (>= 2.3.6), the version
available on CRAN. Additional_repositories removed — every declared
dependency now resolves from CRAN.
plot() on a net_centrality_group gains type = "delta", showing the
between-group difference per measure, and now supports three or more
groups. Zero-valued edges can be blanked with drop_zero = TRUE.plot() on a net_edge_betweenness() result (plot.net_edge_betweenness).plot() on centrality results gains alternative views:
type = c("bar", "line", "heatmap") for a single net_centrality, and
type = c("bar", "line", "delta") for a net_centrality_group. Count-like
measures get integer axis labels.Version bump only; no user-visible changes.
as_htna() — builds a grouped node-level network from data and a
clustering, keeping every node (unlike cluster_summary(), which
collapses to a cluster-level macro summary). Intended for
cograph::plot_htna().Centrality gains the tna-parity measures. net_centrality(x, measures = "all") now returns OutStrength, InStrength, ClosenessIn,
ClosenessOut, Closeness, Betweenness, BetweennessRSP, Diffusion
and Clustering — previously only the strengths, Closeness and
Betweenness. Adds plot.net_centrality and plot.net_centrality_group.
sequence_plot() and the MCML plots gain layout refinements.
as_netobject() / validate_netobject() — the boundary layer between
\pkg{psychnet} (which owns the psychometric-network math and emits a lean
cograph_network) and Nestimate (which owns the canonical netobject
schema). as_netobject() promotes a psychnet result or a bare
cograph_network to the dual-class c("netobject", "cograph_network") so it
dispatches to every Nestimate verb, parking psychnet-specific fields (including
the GLASSO KKT certificate) under $meta$psychnet; netobjects pass through
unchanged. validate_netobject() enforces the shared structural contract so
schema drift on either side fails loudly. psychnet is not a declared
dependency — Nestimate never calls it; the converter works by S3 dispatch on
whatever psychnet object the caller supplies.
certainty() — analytic Bayesian counterpart of bootstrap_network() for
transition networks. Models each state's outgoing transitions as a
Dirichlet-Multinomial process (Jeffreys prior) and returns posterior mean,
sd, credible interval and a stability decision per edge in closed form (no
resampling). Returns the exact net_bootstrap object layout and carries
class c("net_certainty", "net_bootstrap"), so it is a drop-in: every
net_bootstrap method works on it. Completes the assessment trio
certainty / stability (bootstrap_network) / reliability (reliability).
sequence_plot() gains a multichannel view for mcml objects built from
sequences. sequence_plot(fit) draws one carpet panel per cluster channel
plus a macro Summary panel — each channel's own states solid, the other
clusters a faded wash, finished cells white, rows aligned by the macro
sequence. sequence_plot(fit, type = "distribution") stacks the prevalence
(own states + faded other clusters + an explicit NA band, to 100%), and
normalize = TRUE gives a TraMineR-style seqdplot where each time point
sums to 1. ggplot-based and dependency-free; returns a ggplot object.
bayes_compare() results are now 100% compatible with the permutation()
format: the object carries class c("net_bayes", "net_permutation") with all
net_permutation slots (diff_sig, p_values, effect_size, iter,
alpha, paired, adjust), and its summary is a superset of
summary.net_permutation (from, to, weight_x, weight_y, diff, effect_size, p_value, sig plus the Bayesian extras count_x, count_y, ci_lower, ci_upper, ci_width, pd). A bayes_compare() result is now a drop-in wherever a
net_permutation is consumed.
bayes_compare() — Bayesian Dirichlet-Multinomial comparison of two
transition networks, a complement to permutation(). Models each source
state's outgoing transitions as a Dirichlet-Multinomial process (Jeffreys
prior) and returns, per edge, a posterior mean difference, a credible
interval, the probability of direction (pd) and its two-sided
p-equivalent. Adds print/summary/plot methods and netobject_group
dispatch (all-pairwise or matched). Method source: Johnston & Jendoubi
(2026), How Delivery Mode Reshapes Resource Engagement: A Bayesian
Differential Network Analysis, TNA Workshop 2026.as_networks() — promote a build_mcml_pc() result into a
netobject_group (the psychometric-network counterpart of as_tna()).
Singleton clusters with no within-network are dropped with a warning;
an existing netobject_group passes through unchanged.markov_order_test() reads
sequences straight from a fitted network (markov_order_test(net));
HYPA anomaly tables use summary(hypa, order_by = "ratio"); higher-order
pathways use pathways(hon, top = ); grouped-clustering inspection uses
cluster_diagnostics().build_mcml_pc() — MCML aggregation for psychometric networks
(cor / pcor / EBICglasso). Five aggregation methods with explicitly
different statuses: "average" (descriptive block-mean; works without
raw data), "composite" (cluster scores re-estimated with the chosen
estimator — a genuine cluster-level network), "loadings" (composites
weighted by mean within-cluster connection strength — Nestimate's own
weighting, not an EGA reimplementation), "rv" (Escoufier's RV matrix
correlation between blocks), and "canonical" (first canonical
correlation — the upper bound for composite methods). Within-cluster
networks re-estimated by default (within = "reestimate") since a
pcor submatrix is not the subsystem's pcor network. Item diagnostics
in $loadings: signed loadings (reverse-keyed items detected via the
leading eigenvector of the within-block matrix and flipped in
composites), cross-cluster strengths, and a misfit flag when an item
is more connected to another cluster than its own (warned). Composites
tolerate missing data (row-wise renormalized weighted means);
Composite item weights are selectable via weighting — ten built-in
schemes spanning three views of the cluster: the scale as scored
("equal", "item_total"), the network's view ("strength",
"eigen", "closeness", "betweenness", "expected_influence",
"specificity" — the misfit margin as a weighting, zeroing items that
belong as much to another cluster), and the latent-variable view
("pca", "factor"); plus fully custom weighting via a named numeric
vector or a function(W_block, data_block, nodes).
aggregation = "loadings" is the alias for composite + strength.
The "factor" weighting exposes its extraction method via
fa_method: "ml" (factanal), "paf" (iterated principal axis),
"minres" (ULS), or "cfa" (one-factor lavaan model; with
cor_method = "polychoric" the categorical DWLS factor model) — all
operating on the cor_method-consistent correlation structure.
Reverse-keyed handling works under every sign-carrying scheme
(item-total correlations are computed on eigen-sign-pre-oriented
columns so a reversed member cannot contaminate small clusters).
cor_method = "polychoric" (via lavaan) supports ordinal items;
id_col drops identifier columns so
convert_sequence_format(format = "frequency") actor-profiles feed
the function directly (the within-person co-occurrence view of event
data).
Returns class mcml_pc (macro + within netobjects, all undirected)
with print/summary/plot; the composite/loadings macro is a full
netobject, so bootstrap_network(), vertex_bootstrap(), and
vertex_compare() apply to it directly. cograph::plot_mcml()
(>= 2.3.8) renders the two-layer undirected MCML view. Experimental:
API and formulas may change.loading_stability() — case-bootstrap stability of the
build_mcml_pc() composite weights (percentile CIs, sign-flip rates),
with print and forest-style plot.vertex_bootstrap() — Snijders & Borgatti (1999) vertex bootstrap for
network-level statistics (density, mean weight, strength centralization,
weighted reciprocity, plus custom statistic_fn). Needs only the weight
matrix, so it works on data-less netobjects (build_mlvar()
constituents, as_tna(mcml) elements, plain matrices) where
bootstrap_network() cannot run. Returns a tidy one-row-per-statistic
net_vertex_bootstrap with print/summary/plot. Self-loops are preserved
(diagonal carries the resampled vertex's own self-weight); undirected
replicates stay symmetric.vertex_compare() — the Snijders & Borgatti two-network test the
vertex bootstrap was originally proposed for: z-tests and
normal-approximation CIs for differences in network-level statistics
between two networks (netobjects, matrices, or precomputed
net_vertex_bootstrap objects). Tidy net_vertex_comparison result
with print/summary/plot (forest plot of differences).bootstrap_network() and vertex_bootstrap() gain
ci_method = c("percentile", "basic"): basic intervals
(Davison & Hinkley 1997, eq. 5.6) reflect the percentile bounds around
the observed estimate, correcting first-order bootstrap bias. Default
remains "percentile".build_mcml() (sequence and edge-list paths) now records the
effective directedness in $meta$directed: FALSE when
type = "cooccurrence", whose weights are symmetrized, instead of
echoing the directed argument unchanged. Renderers that auto-detect
directedness (e.g., cograph::plot_mcml() with directed = NULL) now
draw co-occurrence MCML objects as undirected networks automatically.mosaic_analysis(data, var1, var2) — two-variable mosaic analysis on a
data.frame: chi-square or Fisher test, Cramer's V (df-adjusted effect
size) and a flat mosaic plot. Returns class mosaic_analysis with a tidy
one-row-per-cell $counts, a one-row $stats, and print/summary/plot.
Distinct from mosaic_plot(), which draws from a fitted network object.mosaic_plot() gains style = c("classic", "flat"). The flat style uses
variable-width columns, white gutters and in-tile or side labels, sharing
the classic style's geometry and diverging palette; values = TRUE prints
residuals inside the tiles.build_network() and the transition wrappers (build_tna(),
build_ftna(), build_atna(), build_cna()) gain start and end
boundary markers: FALSE (default), TRUE (labels "Start" / "End")
or a custom string. start prepends a source state to every sequence;
end places a sink in the single cell after each sequence's last non-NA
state (not absorbing — see mark_terminal_state() for that). Honoured by
the relative, frequency, co_occurrence and attention estimators;
other methods error.
build_mmm() gains covariate_effect. "em" (default) folds covariates
into the EM as covariate-dependent mixing, changing the fit; "posthoc"
fits a plain mixture and uses covariates only for the after-fit
multinomial logit, leaving the clustering bit-identical to a
no-covariate fit.
magnitude_difference() compares the frequency (FTNA) and probability
(TNA) views of a transition network and quantifies the per-edge
discrepancy on a common scale, with five metrics, four scalings, and two
polar plot() portraits (stacked and circular).persistent_homology(), build_simplicial(type = "vr")) plus diagram
tools bottleneck_distance() and persistence_landscape().compare_model() (with netobject_group dispatch),
summary.netobject(), plot.net_comparison(), and rename_models() for
relabelling grouped network objects.magnitude_difference(), casedrop_reliability(), build_hypergraph(),
hypergraph_measures(), and cluster_data() were previously absent.Remotes: field; cograph and tna are available from CRAN,
so no non-CRAN source pin is needed.Followed codex_docs/audit_clustering and codex_docs/audit_mcml
recommendations across two modules. Eleven of thirteen findings
addressed; two deferred pending design decisions on numeric semantics
(directed = FALSE raw-data MCML, MMM first-non-NA initial state).
cluster_network() now forwards distance-clustering arguments
(na_syms, weighted, lambda, seed, q, p, covariates)
to build_clusters() instead of silently passing them to
build_network(). The split runs on caller ... only — netobject
build_args continue to flow only to the build_network() step,
protecting attention-method (atna) network history from being
re-routed to weighted Hamming. (audit_clustering item 1).auto_detect_clusters() (used by build_mcml() and
cluster_summary()) now requires node_groups to carry a node
identifier column when shaped as a data.frame, or be a named atomic
vector keyed by node label. Previously, a bare cluster-only
data.frame was read positionally — silently mis-assigning nodes
whenever node_groups rows were in a different order than x$nodes.
(audit_mcml item 1)build_clusters() now rejects all-missing input early with a clear
message instead of failing indirectly downstream in pam/hclust.
(audit_clustering item 4)compare_mmm(return_fits = FALSE) — when TRUE, the fitted
net_mmm models are attached as attr(result, "fits") keyed by
k, so users can pick the chosen model without re-running EM.
Default behaviour unchanged. (audit_clustering item 6)build_clusters() validation messages now name the offending
argument ("'k' must be at least 2 (got k = 1)") rather than
dumping the failing predicate. Top-level type checks switched to
named-condition stopifnot() for the same reason.
(audit_clustering item 2)summary.mcml() roxygen corrected — was claiming a printing side
effect that doesn't exist. (audit_mcml item 5)build_mcml() clusters = "<col>" mode now documents its narrow
contract: assigns each row's group label to both endpoints, so it
only makes sense for within-group edge lists. (audit_mcml item 2)build_mcml() method parameter doc now steers raw sequence /
event-log inputs to "sum", since the function counts observed
transitions. Other methods are for weighted edge lists or
pre-existing matrices. (audit_mcml item 4)as_tna.mcml() "Excluded Clusters" section corrected — drop emits
a warning() (was claimed silent) and only fires for relative
method (was claimed unconditional). (audit_mcml item 6)build_clusters() na_syms doc adds an explicit "Missing-value
distance rule" subsection: NA becomes a comparable sentinel state,
not pairwise deletion. (audit_clustering item 3)build_mmm() adds an "Initial states" section explaining
first-column-verbatim init and that build_mmm does NOT honor
build_clusters-style na_syms — only actual NA cells become NA
inits. (audit_clustering item 5, doc-only path)node_groups alignment, label propagation
through state_distribution(), as_tna.mcml() drop-warning
fixture, MMM first-column NA behaviour, and the four-way
cluster_network() arg-routing contract). Full sweep:
1628 / 1628 pass, 0 fail..extract_edges_from_matrix() no longer drops the diagonal. Netobjects
built via .wrap_netobject() (and therefore everything from
build_network(), build_mcml(), bootstrap_network(), build_mmm(),
wtna(), as_tna()) now have $edges containing every non-zero
matrix entry, including self-loops. Previously $weights and $edges
were silently inconsistent on any matrix with a non-zero diagonal,
causing downstream consumers (e.g. cograph::centrality() on an
MCML macro) to under-count node degree by 2.plot_state_frequencies() — native S3 generic for state-frequency
plots across netobject, netobject_group, mcml, and htna.
Defaults to a marimekko (mosaic) layout where column widths reflect
per-group totals and segment heights reflect within-group state
proportions; also supports a colored-bars style and a per-group
faceted marimekko. Uses the package Okabe-Ito palette throughout.plot_mosaic() — exported low-level marimekko primitive built on
geom_rect() with cumulative-width / cumulative-height geometry.
Reusable for any tidy data.frame(group, state, weight) input.passage_time() and markov_stability() now raise an explicit error
naming the dead state when a transition-matrix row sums to zero,
instead of silently propagating NaN through eigen/solve. Zero
rows mean the chain is not ergodic; mean first passage times are
undefined. Shared helper .mpt_normalize_rows() factored out of both
entry points..prepare_association_input() no longer hard-rejects non-square
numeric matrices. For association methods (glasso, pcor, cor) the
netobject's $data slot is a numeric matrix (not a data.frame). Any
downstream caller that row-subsetted $data and re-invoked the
estimator (centrality_stability(), bootstrap_network(),
reliability()) was silently producing NULL centralities caught by
tryCatch, which surfaced as an "all centrality measures have zero
variance" warning or all-NaN correlations. The matrix branch now
recognises non-square input as raw observation data and recursively
re-enters through the data-frame branch. Square symmetric matrices
(pre-computed correlation / covariance) still go through the
symmetric-matrix path with the symmetry check intact.build_network() gains state_cols and metadata_cols parameters
(both default NULL). Explicit overrides for the state-vs-metadata
column classifier, which previously used a "values-in-nodes"
heuristic that silently misclassifies metadata columns whose values
coincide with node labels (e.g. a condition column with levels
"A","B","C" when nodes are "A","B","C"). Validation: error on
overlap between the two vectors, error on column names not present
in the input data. Forwarded through the group = ... recursive
dispatch so per-group calls honour the override.plot.net_link_prediction() and plot.mcml() removed. Nestimate is
a computation engine — visualization is the user's concern.
Previously both methods called cograph:: directly, violating the
stated dependency invariant (Nestimate -> cograph direction
forbidden). Users call cograph::splot(net) or
cograph::plot_mcml(fit) directly.wtna() @param type now flags that type = "relative" combined
with method = "cooccurrence" produces an asymmetric matrix
(conditional co-occurrence given row state), not a symmetric
undirected weight matrix. Use type = "frequency" if symmetric
counts are required.NESTIMATE_EQUIV_TESTS=true):
test-equiv-permutation.R (vs. stats::p.adjust + hand-coded base-R
permutation loop), test-equiv-mlvar.R (vs. mlVAR::mlVAR at
machine precision), test-equiv-association-rules.R (vs.
arules::apriori), test-equiv-link-prediction.R (vs. clean-room
matrix algebra + igraph::similarity), test-equiv-centrality-stability.R
(vs. bootnet::corStability). Total ~162k per-value comparisons;
all within machine precision except centrality-stability which uses
a documented drop-grid tolerance because bootnet uses igraph
path-based centrality and Nestimate uses Floyd-Warshall.local_testing_and_equivalence/
validating HON, HONEM, HYPA, MOGen, and hypergraph against pathpy
2.2.0 (via reticulate), BiasedUrn, RSpectra, and HyperG. Not
shipped in the R-package tests/ directory; added to .Rbuildignore.wtna,
bootstrap_network, build_clusters, sequence_plot) — systematic
cross-product tests over all combinations of mode parameters to
catch regressions where one branch silently diverges.build/vignette.rds (the vignette index). Previous 0.4.2 build used R CMD build --no-build-vignettes, which preserved pre-built inst/doc/*.html but stripped the index — CRAN flagged "VignetteBuilder field but no prebuilt vignette index."test-gimme.R now skip_on_cran(). GIMME tests fit a lavaan SEM per subject and took ~50s locally (2-3× on Windows), pushing total check time to 11 min on win-devel. Full test suite still runs in CI and local dev.--as-cran --run-donttest audit pass..Rcheck/ and Meta/ build artifacts from working tree; added explicit ^Nestimate\.Rcheck$ and ^\.\.Rcheck$ entries to .Rbuildignore as belt-and-suspenders against repeat-submission contamination.inst/doc/ as required by CRAN.skip_on_cran() to slow test block to keep check time under 10 minutes.build_mlvar() — multilevel VAR networks from ESM/EMA panel data. Estimates temporal (directed), contemporaneous (undirected), and between-subjects (undirected) networks matching mlVAR::mlVAR() at machine precision.build_mmm() / compare_mmm() — mixture of Markov models via EM, with BIC/AIC/ICL model selection and optional covariate regression.cooccurrence() — standalone co-occurrence network builder supporting 6 input formats and 8 similarity methods.sequence_compare() — k-gram pattern comparison across groups with optional permutation testing.sequence_plot() / distribution_plot() — base-R sequence index and state distribution plots with clustering integration.build_simplicial(), persistent_homology(), q_analysis() — topological analysis of networks via simplicial complexes.nct() — Network Comparison Test matching NetworkComparisonTest::NCT() at machine precision.build_gimme() — group iterative mean estimation for idiographic networks via lavaan.passage_time(), markov_stability() — Markov chain passage times and stability analysis.predict_links() / evaluate_links() — link prediction with 6 structural similarity methods.association_rules() — Apriori association rule mining from sequences or binary matrices.predictability() — node predictability for glasso/pcor/cor networks.build_hon(), build_honem(), build_hypa(), build_mogen() — higher-order network methods (HON, HONEM, HYPA, MOGen) now cograph_network-compatible.human_long, ai_long — canonical long-format human–AI pair programming interaction sequences (10,796 turns, 429 sessions).chatgpt_srl — ChatGPT-generated SRL scale scores for psychological network analysis.trajectories — 138-student engagement trajectory matrix (15 timepoints, 3 states).build_clusters(), network_reliability(), permutation(), and prepare() replace earlier internal names for consistency with the build_* naming convention.mgm estimator added (method = "mgm") for mixed continuous + categorical data via nodewise lasso, matching mgm::mgm() at machine precision.build_mmm() no longer crashes on platforms where parallel::detectCores() returns NA (macOS ARM64 CRAN check failure).gimme convergence filter now correctly handles all typed NA variants (NA_character_, NA_real_, etc.).NaN values in numeric metadata aggregation (all-NA sessions) normalized to NA_real_.hypa_score column renamed to p_value..data pronoun added to globalVariables().base::.rowSums() / base::.colSums() replaced with rowSums() / colSums().dev.new() guarded by interactive() — no side effects under knitr or CI.do.call(rbind, ...) replaced with data.table::rbindlist() in mcml.R and sequence_compare.R.hypa_score column to p_value for clarity. Added $over, $under, $n_over, $n_under fields to net_hypa objects. Scores are now pre-sorted with anomalous paths first.summary.net_hypa() now shows over/under-represented paths separately with a configurable n parameter.pathways.netobject(): New S3 method to extract higher-order pathways directly from a netobject (builds HON or HYPA internally).path_counts(): Now handles NAs in trajectories by stripping them before k-gram counting.centrality_stability() and boot_glasso() now accept a centrality_fn parameter for external centrality computation.graphical_var() from scratch using coordinate descent lasso + graphical lasso with EBIC model selection, eliminating the graphicalVAR dependency.ml_graphical_var() — users should use mlvar() for multilevel VAR.plot.netobject(), plot.net_bootstrap(), plot.net_permutation(), plot.net_hon(), plot.net_hypa() and as_cograph() removed. Users call cograph plotting functions directly on netobjects.attention estimator for decay-weighted transition networks.build_network() with 8 built-in estimators.bootstrap_network()), permutation testing (permutation()), EBICglasso bootstrap (boot_glasso()).c("netobject", "cograph_network") output for cograph compatibility.