Manipulating the nodes of a network structure

In many cases, the nodes of a Bayesian network are fixed quantity that is not subject to change; for instance, when learning its structure from data the nodes in the network correspond to the variables in the data. However, sometimes it can be useful to be able to manipulate the nodes in a network structure for studying its theoretical properties.

Adding and removing nodes

bnlearn provides two functions to manipulate node sets: add.node() and remove.node(). Both operate on objects of class bn, and take the label of a node as their second argument. add.node() add the node to the network.

> library(bnlearn)
> 
> dag = model2network("[A][B][C][F][G][D|C][H|C:F][E|D][I|A:F:H][J|E]")
> larger.dag = add.node(dag, "K")
> dag

  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
> larger.dag

  Random/Generated Bayesian network

  model:
   [A][B][C][F][G][K][D|C][H|C:F][E|D][I|A:F:H][J|E] 
  nodes:                                 11 
  arcs:                                  8 
    undirected arcs:                     0 
    directed arcs:                       8 
  average markov blanket size:           2.00 
  average neighbourhood size:            1.45 
  average branching factor:              0.73 

  generation algorithm:                  Empty

The new node (K above) added to larger.dag is isolated; larger.dag has the same arcs as dag.

remove.node() works the other way round: it removes a node from the network, and in doing removes all the arcs that are incident on that node.

> smaller.dag = remove.node(larger.dag, "I")
> smaller.dag

  Random/Generated Bayesian network

  model:
   [A][B][C][F][G][K][D|C][H|C:F][E|D][J|E] 
  nodes:                                 10 
  arcs:                                  5 
    undirected arcs:                     0 
    directed arcs:                       5 
  average markov blanket size:           1.20 
  average neighbourhood size:            1.00 
  average branching factor:              0.50 

  generation algorithm:                  Empty

As a result, smaller.dag has three fewer arcs because AI, FI and HI are removed along with node I.

Renaming nodes

The nodes() function returns the labels of the nodes in a bn object. (It does the same for a bn.fit object.)

> nodes(dag)
 [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J"

The assignment version of nodes() replaces the labels with new ones, effectively renaming the nodes.

> nodes(dag) = c("X01", "X02", "X03", "X04", "X05", "X06", "X07", "X08", "X09", "X10")
> dag

  Random/Generated Bayesian network

  model:
   [X01][X02][X03][X06][X07][X04|X03][X08|X03:X06][X05|X04][X09|X01:X06:X08]
   [X10|X05]
  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

The labels of the nodes in the arc set are replaced as well for consistency.

> arcs(dag)
     from  to   
[1,] "X03" "X04"
[2,] "X03" "X08"
[3,] "X06" "X08"
[4,] "X04" "X05"
[5,] "X01" "X09"
[6,] "X06" "X09"
[7,] "X08" "X09"
[8,] "X05" "X10"

In fact, the assignment version of nodes() is an alias of the rename.nodes() function, which does the same thing but has a more discoverable and easy-to-guess name. Hence the above is equivalent to the following.

> dag = rename.nodes(dag, names = c("X01", "X02", "X03", "X04", "X05",
+                                   "X06", "X07", "X08", "X09", "X10"))
> dag

  Random/Generated Bayesian network

  model:
   [X01][X02][X03][X06][X07][X04|X03][X08|X03:X06][X05|X04][X09|X01:X06:X08]
   [X10|X05]
  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
Last updated on Sat Feb 17 23:32:39 2024 with bnlearn 5.0-20240208 and R version 4.3.2 (2023-10-31).