Reputation: 1883
How do I convert a graphviz.dot.Digraph
into a networkx.Graph
(or any subclass of it)?
LightGBM, an implementation of a tree-based algorithm, has a function returning a graphviz.dot.Digraph
object. This type of object can represent any directed graph, but my graph is specifically a tree, and thus can be represented in JSON via a simpler nested structure:
var tree = {
"name": "parent",
"children": [
{
"name": "child_1"
}
{
"name": "child_2"
}
[
}
Another, longer example of the above JSON structure is here. I use this JSON format to create a tree visualization using d3
in javascript
.
In total, I need to convert this graphviz.dot.Digraph
object to the above nested-JSON format.
If I can convert this graphviz.dot.Digraph
object into a networkx.Graph
object, I can use this method to convert it to the required JSON format. This intermediate conversion has been problematic for me. It seems I need another conversion to something networkx
can use.
Upvotes: 2
Views: 3741
Reputation: 1883
One method of converting graphviz.dot.Digraph
to a networkx.Graph
is to convert it to a pydotplus.graphviz.Dot
object, and convert that into a networkx.classes.multidigraph.MultiDiGraph
object which inherets from graph
.
#--------------------
# Do whatever it is you do to create the graphviz.Digraph object
import lightgbm as lgbm
# .......
digraph = lgbm.create_tree_digraph(model)
print(type(digraph)) # prints <class 'graphviz.dot.Digraph'>
#--------------------
# Perform the conversion to networkx
import pydotplus
import networkx
dotplus = pydotplus.graph_from_dot_data(digraph.source)
print(type(dotplus)) # prints <class 'pydotplus.graphviz.Dot'>
# if graph doesn't have multiedges, use dotplus.set_strict(true)
nx_graph = networkx.nx_pydot.from_pydot(dotplus)
print(type(nx_graph)) # prints <class 'networkx.classes.multidigraph.MultiDiGraph'>
The rest is just for people considering conversion to JSON
#--------------------
# Optionally, convert to json
import json
# must specify whatever node is the root of the tree, here its 'split0'
# or you can try list(graph)[0] if you're not sure.
data = networkx.readwrite.json_graph.tree_data(nx_graph,root='split0')
# data is just a dictionary. Dump results in proper json format.
json.dump(data,open(file_path,'w'))
Later I found out LightGBM actually has a dump_model method that shortcuts all of this...but I'll leave this here.
Upvotes: 1