Creates a Graphviz DOT script that visualizes the structural network
estimated by nmf.sem.
The resulting diagram displays:
endogenous observed variables (\(Y_1\)),
exogenous observed variables (\(Y_2\)),
latent factors (\(F_1\), ..., \(F_Q\)),
together with the non-negative path coefficients whose magnitudes exceed a user-specified threshold.
Directed edges represent estimated relationships:
\(Y_2 \rightarrow F_q\): entries of
C2(exogenous loadings),\(F_q \rightarrow Y_1\): rows of
X(factor-to-endogenous mappings),\(Y_1 \rightarrow F_q\): entries of
C1(feedback paths).
Edge widths are scaled by coefficient magnitude, and nodes are placed in optional visual clusters. Only variables participating in edges above the threshold are displayed, while latent factors are always shown.
Usage
nmf.sem.DOT(
result,
weight_scale = 5,
weight_scale_y2f = weight_scale,
weight_scale_fy1 = weight_scale,
weight_scale_feedback = weight_scale,
threshold = 0.01,
rankdir = "LR",
fill = TRUE,
cluster.box = c("normal", "faint", "invisible", "none"),
cluster.labels = NULL,
hide.isolated = TRUE,
sig.level = 0.1
)Arguments
- result
A list returned by
nmf.sem, containing matricesX,C1, andC2.- weight_scale
Base scaling factor for edge widths.
- weight_scale_y2f
Optional override for scaling edges \(Y_2 \rightarrow F_q\). Defaults to
weight_scale.- weight_scale_fy1
Optional override for scaling edges \(F_q \rightarrow Y_1\). Defaults to
weight_scale.- weight_scale_feedback
Optional override for scaling feedback edges \(Y_1 \rightarrow F_q\). Defaults to
weight_scale.- threshold
Minimum coefficient value needed for an edge to be drawn.
- rankdir
Graphviz rank direction (e.g.,
"LR","TB").- fill
Logical; whether to use filled node shapes.
- cluster.box
Character string controlling the visibility and style of cluster frames around Y2, factors, and Y1 blocks. One of
"normal","faint","invisible","none".- cluster.labels
Optional character vector of length 3 giving custom labels for the Y2, factor, and Y1 clusters.
- hide.isolated
Logical. If
TRUE(default), Y1 and Y2 nodes that have no edges at or abovethresholdare excluded from the graph.- sig.level
Significance level for filtering C2 edges when inference results are present. If
resultcontains acoefficientsdata frame (fromnmf.sem.inference), only edges withp_value < sig.levelare drawn, with significance stars appended. Set toNULLto disable filtering. Default is0.1.
Examples
Y <- t(iris[, -5])
Y1 <- Y[1:2, ]
Y2 <- Y[3:4, ]
result <- nmf.sem(Y1, Y2, rank = 2, maxit = 500)
dot <- nmf.sem.DOT(result)
cat(dot)
#> digraph NMF_SEM_Full_Mechanism {
#> graph [rankdir=LR compound=true];
#> splines=true; nodesep=0.4; ranksep=0.7; fontname="Arial";
#>
#> // Exogenous variables (Y2)
#> subgraph cluster_Y2{label="Exogenous (Y2)" style="rounded" color="black" penwidth=1.0;
#> node [shape=box, style="filled,rounded", fillcolor="lightcoral", color=black, penwidth=1.5];
#> Y2_1 [label="Petal.Length"];
#> }
#>
#> // Endogenous variables (Y1)
#> subgraph cluster_Y1{label="Endogenous (Y1)" style="rounded" color="black" penwidth=1.0;
#> node [shape=box, style="filled,rounded", fillcolor="lightblue", color=black, penwidth=1.5];
#> Y1_1 [label="Sepal.Length"];
#> Y1_2 [label="Sepal.Width"];
#> }
#>
#> // Latent Factors (F)
#> subgraph cluster_F{label="Latent Factors" style="rounded" color="black" penwidth=1.0;
#> node [shape=ellipse, style="filled,rounded", fillcolor="wheat", color=black, penwidth=1.0];
#> F_1 [label="Factor 1"];
#> F_2 [label="Factor 2"];
#> }
#>
#> edge [fontname="Arial", fontsize=8, arrowhead=open];
#>
#> // 1. External Driving (Y2 -> Factor) [C2]
#> edge [color=black, fontcolor=black, style=solid];
#> Y2_1 -> F_1 [label="0.15", penwidth=5.00];
#>
#> // 2. Generation (Factor -> Y1) [X]
#> edge [color="gray0", fontcolor="gray0", style=solid];
#> F_1 -> Y1_1 [label="0.99", penwidth=5.00];
#> F_2 -> Y1_2 [label="0.99", penwidth=5.00];
#>
#> // 3. Internal Feedback (Y1 -> Factor) [C1]
#> edge [style=dashed, color="gray0", fontcolor="gray0"];
#> Y1_1 -> F_1 [label="0.74", penwidth=3.87];
#> Y1_2 -> F_1 [label="0.31", penwidth=1.65];
#> Y1_1 -> F_2 [label="0.02", penwidth=0.50];
#> Y1_2 -> F_2 [label="0.96", penwidth=5.00];
#> }