rigraphcategorical-databayesian-networksbnlearn

Bayesian networks 'catnet' package cnPlot returning null


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.

Creating a catnetwork:

 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))
)

Setting empirical probabilities

cnet2 <- catnet::cnSetProb(cnet, data=ais_v2.sub)

Plotting the network

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

Solution

  • 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)