I am working with Bayesian Networks for the first time and I am using Catnet package in R. The reason being my data is full of categorical variables and a lot of missing data too. I tried the simple example posted elsewhere in StackOverflow just to get a sense of how it works. While it is able to produce the conditional probabilities of each of the nodes in the network, I am not able to visualize the network graphically for an easier understanding. The cnPlot(catNetwork)
just returns null. I was wondering if someone with experience using CatNet can point me to the problems with my approach. Thanks.
cnet <- catnet::cnNew(
nodes = c("sport", "high_hc", "high_hg"),
cats = list(c("1","2"), c("1","2"), c("1","2")),
parents = list(NULL, NULL, c(1,2))
)
cnet2 <- catnet::cnSetProb(cnet, data=ais_v2.sub)
Sys.setenv(R_CATNET_USE_IGRAPH=TRUE)
cnPlot(cnet2)
The plot, in the end, returns null. I have also imported igraph library. Not sure what is going on.
For a reproducible example, I tried the same approach as in this thread:
The code example is below:
#rm(list=ls())
### generate random data (not simply independent binomials)
set.seed(123)
n.obs <- 10
a1 <- rbinom(n.obs,1,.3)
a2 <- runif(n.obs)
a3 <- floor(-3*log(.25+3*a2/4))
a3[a3>=2] <- NA
a2 <- floor(2*a2)
my.data <- data.frame(a1,a2,a3 )
### discretize data into proper categories
my.data <- cnDiscretize(my.data,numCategories=2)
my.data
## say we want a2 conditional on a1,a3
## first generate a network with a1,a3 ->a2
cnet <- cnNew(
nodes = c("a1", "a2", "a3"),
cats = list(c("1","2"), c("1","2"), c("1","2")),
parents = list(NULL, c(1,3), NULL)
)
## set the empirical probabilities from data=my.data
cnet2 <- cnSetProb(cnet,data=my.data)
## to get the conditional probability table
cnProb(cnet2,which='a2')
The output of cnProb is:
$a2
a1 a3 1 2
A 1.0 1.0 0.0 1.0
B 1.0 2.0 0.5 0.5
A 2.0 1.0 0.5 0.5
B 2.0 2.0 0.5 0.5
But when trying to plot,
cnPlot(cnet2)
it returns,
NULL
Similarly for me, the example from ?cnPlot
also produces NULL
and no R plot. Adding a file argument produces no output either. cnDot(cnet, "cnet")
produces an external dot
file which can be rendered with graphviz
but this is not ideal.
If you can get the adjacency matrix or edge list you could pass this to igraph
or Rgraphiz
to plot the net manually; catnet
has the cnMatParents
function to return the adjacency matrix.
Then just need to define a plot function that takes an adjacency matrix as input. In the function below the plot type can be set to "i"
fro igraph
or "d"
for graphviz
/dot
via Rgraphviz
.
plotAdj <- function(adjMAT, type="d", ...){
if(type == "d") {
g = new("graphAM", adjMat=t(adjMAT), edgemode="directed")
Rgraphviz::plot(g, ...)
} else if(type == "i"){
g = igraph::graph_from_adjacency_matrix(t(adjMAT))
plot(g, ...)
}
invisible(g) # return the graph object
}
And use like
library(catnet)
set.seed(123)
cnet1 <- cnRandomCatnet(numnodes=4, maxParents=2, numCategories=2)
adj <- cnMatParents(cnet1) # extract adjacency matrix
p <- plotAdj(adj, type="i", vertex.color="lightblue")
p # return igraph object
library(Rgraphviz)
p <- plotAdj(adj, type="d", attrs = list(node = list(fillcolor = "lightblue")))
p # return Rgraphviz object
bnlearn
and gRain
both have nice plotting methods.
Page 3 of the catnet reference doc
shows how to render the dot
file and open a pdf viewer automatically. On linux, the following opens up a pdf with the plot
Sys.setenv(R_DOTVIEWER="/usr/bin/dot") # path to dot on my system
cnPlot(cnet1)