Interfacing with the graph R package
The graph package (link) is available from Bioconductor and it is one of the most popular packages to work on graphs (both directed and undirected). It implements a variety of algorithms for random graph generation, centrality statistics, graph distances, nodes and arcs manipulation utilities, and it provides a strong foundation for the Rgraphviz package (link). For this reason, bnlearn implements functions to import and export network structures to graph as:
graphNEL
objects, which encode the graph as a list in which each element refer to one of the nodes in the graph and contains a vector with its children;graphAM
objects, which encode the graph as a matrix in which the (i, j) cell is equal to one if there is an arc from the ith node to the jth node and zero otherwise.
Exporting a network structure to graph
Exporting the objects is achieved with the conversion methods as.graphNEL()
and
as.graphAM()
.
> library(bnlearn) > > dag.bnlearn = random.graph(LETTERS[1:10]) > dag.bnlearn
Random/Generated Bayesian network model: [A][B][C][F][G][D|C][H|C:F][E|D][I|A:F:H][J|E] nodes: 10 arcs: 8 undirected arcs: 0 directed arcs: 8 average markov blanket size: 2.20 average neighbourhood size: 1.60 average branching factor: 0.80 generation algorithm: Full Ordering arc sampling probability: 0.2222222
> dag.graphNEL = as.graphNEL(dag.bnlearn) > dag.graphNEL
A graphNEL graph with directed edges Number of Nodes = 10 Number of Edges = 8
> dag.graphAM = as.graphAM(dag.bnlearn) > dag.graphAM
A graphAM graph with directed edges Number of Nodes = 10 Number of Edges = 8
Both methods accept objects of class bn.fit
as well as of class bn
,
and they implicitly call bn.net()
(link)
on the former to export them.
> dag.test = hc(learning.test) > dag.test
Bayesian network learned via Score-based methods model: [A][C][F][B|A][D|A:C][E|B:F] nodes: 6 arcs: 5 undirected arcs: 0 directed arcs: 5 average markov blanket size: 2.33 average neighbourhood size: 1.67 average branching factor: 0.83 learning algorithm: Hill-Climbing score: BIC (disc.) penalization coefficient: 4.258597 tests used in the learning procedure: 40 optimized: TRUE
> fitted = bn.fit(dag.test, learning.test) > as.graphNEL(fitted)
A graphNEL graph with directed edges Number of Nodes = 6 Number of Edges = 5
> as.graphAM(fitted)
A graphAM graph with directed edges Number of Nodes = 6 Number of Edges = 5
Undirected arcs are exported as a pair of directed arcs, that is, Xi — Xj becomes {Xi → Xj, Xi ← Xj}.
> as.graphNEL(skeleton(dag.test))
A graphNEL graph with directed edges Number of Nodes = 6 Number of Edges = 10
Importing a network structure from graph
Importing network structures works in the same way, with a conversion method as.bn()
.
> as.bn(dag.graphAM)
Random/Generated Bayesian network model: [A][B][C][F][G][D|C][H|C:F][E|D][I|A:F:H][J|E] nodes: 10 arcs: 8 undirected arcs: 0 directed arcs: 8 average markov blanket size: 2.20 average neighbourhood size: 1.60 average branching factor: 0.80 generation algorithm: Empty
> as.bn(dag.graphNEL)
Random/Generated Bayesian network model: [A][B][C][F][G][D|C][H|C:F][E|D][I|A:F:H][J|E] nodes: 10 arcs: 8 undirected arcs: 0 directed arcs: 8 average markov blanket size: 2.20 average neighbourhood size: 1.60 average branching factor: 0.80 generation algorithm: Empty
Note that as graphs are imported with as.bn()
they are checked to be acyclic, unless
the user specifies check.cycles = FALSE
.
> library(graph) > > m = matrix(rep(0, 9), nrow = 3, ncol = 3) > m[1, 2] = m[2, 3] = m[3, 1] = 1 > cyclic = graphAM(m, edgemode = "directed") > as.bn(cyclic)
## Error: the graphAM object contains directed cycles.
> as.bn(cyclic, check.cycles = FALSE)
Random/Generated Bayesian network model: [n1|n3][n2|n1][n3|n2] nodes: 3 arcs: 3 undirected arcs: 0 directed arcs: 3 average markov blanket size: 2.00 average neighbourhood size: 2.00 average branching factor: 1.00 generation algorithm: Empty
Mon Aug 5 02:49:15 2024
with bnlearn
5.0
and R version 4.4.1 (2024-06-14)
.