## 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.

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]")
> 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 `A``I`, `F``I` and `H``I` 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)
```
```  "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 `Tue Nov 8 16:12:14 2022` with bnlearn `4.9-20221107` and `R version 4.2.2 (2022-10-31)`.