Extract and analyze triad motifs from network data with flexible filtering, pattern selection, and statistical significance testing. Supports both individual-level analysis (with tna objects or grouped data) and aggregate analysis (with matrices or networks). The supplied adjacency is classified as directed dyads using the 16-class MAN system.
extract_motifs(
x = NULL,
data = NULL,
id = NULL,
level = NULL,
edge_method = c("any", "expected", "percent"),
edge_threshold = 1.5,
pattern = c("triangle", "network", "closed", "all"),
exclude_types = NULL,
include_types = NULL,
top = NULL,
by_type = FALSE,
min_transitions = 5,
significance = FALSE,
n_perm = 100,
seed = NULL
)# S3 method for cograph_motif_analysis
print(x, n = 20, ...)
A cograph_motif_analysis object (list) containing:
Data frame with one row per node-triple and MAN type,
the display label triad, unambiguous node1/node2/
node3 columns, its observed count, and (if
significance = TRUE) expected
count, z-score, empirical p-value, and significance marker. A node
triple that has different types across individuals therefore appears
in more than one row.
Summary counts by motif type across individuals.
List of parameters used
Input data. Can be:
A tna object (supports individual-level analysis)
A matrix (aggregate analysis only, unless data and id provided)
A cograph_network object
An igraph object
Optional data.frame containing transition data with an ID column
for individual-level analysis. Required columns: from, to, and the
column(s) specified in id. If provided, x should be NULL or a matrix
of node labels.
Column name(s) identifying individuals/groups in data. Can be
a single string or character vector for multiple grouping columns.
Required for individual-level analysis with non-tna inputs.
Analysis level: "individual" counts how many people have each triad, "aggregate" analyzes the summed/single network. Default depends on input: "individual" for tna or when id provided, "aggregate" otherwise.
Method for determining edge presence:
Edge exists if count > 0 (simple, recommended)
Edge exists if observed/expected >= threshold
Edge exists if edge/total >= threshold
Default "any".
Threshold value for "expected" or "percent" methods. For "expected", a ratio (e.g., 1.5 means 50\ The default 1.5 is calibrated for this method. For "percent", a proportion (e.g., 0.15 for 15\ When using "percent", set this explicitly (e.g., 0.15). Ignored when edge_method = "any". Default 1.5.
Pattern filter for which triads to include:
All 3 node pairs must be connected (any direction). Types: 030C, 030T, 120C, 120D, 120U, 210, 300. Default.
Exclude simple sequential patterns (chains/single edges). Excludes: 003, 012, 021C. Includes stars and triangles.
Network without chain patterns. Excludes: 003, 012, 021C, 120C. Similar to network but also removes mutual+chain (120C).
Include all 16 MAN types, no filtering.
Character vector of MAN types to explicitly exclude. Applied after pattern filter. E.g., c("300") to exclude cliques.
Character vector of MAN types to exclusively include. If provided, only these types are returned (overrides pattern/exclude).
Return only the top N results (by observed count or z-score). NULL returns all results. Default NULL.
If TRUE, group results by MAN type in output. Default FALSE.
At individual level: minimum total transitions for a person to be included in the analysis. At aggregate level: minimum triad weight to count as present. Default 5.
Logical. Run permutation significance test? Default FALSE.
Number of permutations for the significance test. When
significance = TRUE, must be a whole number of at least 2.
Default 100.
Random seed for reproducibility.
Number of motif rows to print.
Passed to methods; currently unused.
The 16 triad types use MAN (Mutual-Asymmetric-Null) notation where:
First digit: number of Mutual (bidirectional) pairs
Second digit: number of Asymmetric (one-way) pairs
Third digit: number of Null (no edge) pairs
Letter suffix: subtype variant (C=cycle, T=transitive, D=down, U=up)
030C (cycle), 030T (feed-forward), 120C (regulated cycle), 120D (two out-stars), 120U (two in-stars), 210 (mutual+asymmetric), 300 (clique)
021D (out-star), 021U (in-star), 102 (mutual pair), 111D (out-star+mutual), 111U (in-star+mutual), 201 (mutual+in-star), plus all triangle patterns
012 (single edge), 021C (A->B->C chain)
003 (no edges)
Both individual and aggregate significance in this legacy extractor
use a directed weighted stub-matching null: positive weights retain at least
one integer stub, shuffled targets preserve the integerized in/out margins,
and generated loops/parallel edges are reduced to a simple loopless
projection for triad classification. This differs from aggregate
motifs(), which delegates to motif_census() and its simple-graph rewiring
null. Observed self-loops are excluded before activity gating, counting, and
null construction.
The selected edge_method is reapplied to each null replicate, but
positive fractional weights retain at least one integer stub. This preserves
support while potentially changing the mass scale used by
"percent"/"expected" inference. Descriptive results and the
default edge_method = "any" are unaffected.
motifs(), subgraphs(), extract_triads(), motif_census()
Other motifs:
extract_triads(),
get_edge_list(),
motif_census(),
motifs(),
plot.cograph_motif_analysis(),
plot.cograph_motifs(),
subgraphs(),
triad_census()
# Small aggregate example -- no significance test for speed
mat <- matrix(c(0,3,2,0, 0,0,5,1, 0,0,0,4, 2,0,0,0), 4, 4, byrow = TRUE)
rownames(mat) <- colnames(mat) <- c("Plan","Execute","Monitor","Adapt")
m <- extract_motifs(mat, significance = FALSE)
print(m)
if (FALSE) { # requireNamespace("tna", quietly = TRUE)
# \donttest{
Mod <- tna::tna(head(tna::group_regulation, 100))
# Individual-level from tna -- keep n_perm tiny for example speed
extract_motifs(Mod, top = 10, significance = TRUE, n_perm = 10L, seed = 1)
# Filter to feed-forward loops only
extract_motifs(Mod, include_types = "030T", significance = FALSE)
# }
}
Run the code above in your browser using DataLab