Reputation: 61
I built a network with bnlearn, but there are some nodes without edges to another node, so I would like to remove them. Is there a command to remove a specific node from a bn object?
Upvotes: 3
Views: 1649
Reputation: 377
I interpreted this question a little differently, for me, in R this was my approach: Given we have a network iam:
all_nodes <- nodes(iam)
# Find connected nodes
connected_nodes <- unique(unlist(
lapply(all_nodes, function(n) mb(iam, n))))
# Create a subgraph with only the connected nodes
connected_graph <- subgraph(iam, connected_nodes)
Upvotes: 0
Reputation: 15777
bnlearn
has built-in arc operations (docs also here) made for just this. These functions also have the benefit of checking for cycles in your graph, because Bayesian Networks need to be acyclic (directed acyclic graphs, or DAGs), otherwise you get infinite loops and can't calculate conditional probabilities. There's also a check.illegal
argument that checks for another violation of the model when adding an arc (see the docs).
But, their example is not great and neither are the docs. The operations return a model, so you have to overwrite your old model with the returned one.
data(learning.test)
# model ends up the same every time here, but may want
# to set random seed for reproducibility in other cases
set.seed(42)
model = tabu(learning.test) # tabu is a better algo than hc I think
plot(model)
model <- set.arc(model, "A", "F")
plot(model)
model <- drop.arc(model, "A", "F")
plot(model)
set.edge
sets undirected edges, while set.arc
sets directed edges.
Upvotes: 3
Reputation: 19
Fabiola's answer help me a lot.
Here it is a way to do the same but without having to change the model string by hand.
This is the first time I answer a question, so, please be easy on me regarding format.
"net" is my network, "TARGET_NODE" is the node I want to predict (I am including it within the list to be double sure I don't delete it) and "uniq" my dataset.
model.string <- modelstring(net)
final_nodes <- unique(c(unlist(list(net$arcs)), TARGET_NODE))
nodes_to_delete <- paste("\\[",setdiff(names(net$nodes), final_nodes),"]", sep = "")
for (i in 1:length(nodes_to_delete)) {model.string <- gsub(nodes_to_delete[i], "", model.string)}
net <- model2network(model.string)
cols <- c(match(final_nodes, names(uniq)))
uniq <- uniq[,cols]
Upvotes: 1
Reputation: 272
So my attempt for this has been to use the modelstring
function. Get the string, remove the node I know it hasn't any arcs/edges - I do this by hand -, save to a new modified string and then convert the string to a network again with the command model2network
. Here is the sequence of commands:
model.string <- modelstring(mymodel)
model.string
new.string <- "your string except the node you want to remove from the output above"
new.model <- model2network(new.string)
I guess that would work if you don't have many nodes in total (I've got 22) and you just want to remove a few from the list.
Hope that helps!
Upvotes: 1