Problem with drawing Networkx node and edge labels with Pydot. It just doesn't show

368 Views Asked by At

I've met a problem with drawing Networkx node and edge labels, if anyone knows how to fix this please show me how.

I'm building a converter which converts a Pandas dataframe to a graph with NetworkX and Pydot. This is my dataframe looks like: https://i.stack.imgur.com/8aLVZ.jpg

I set "Number" as nodes in NetworkX, and "Title" as labels of the nodes. So I checked the G.nodes, its output looks like this:

[(1000, {'Title': 'Feel boring.'}), (1100, {'Title': 'Play'}), (1110, {'Title': 'Play Cards'}), (1120, {'Title': 'Play Basketball'}), (1130, {'Title': 'Play Video Game'}), (1131, {'Title': 'Open Steam'}), (2000, {'Title': 'Feel Hungry'}), (2100, {'Title': 'Eat'}), (2110, {'Title': 'McDonalds'}), (2120, {'Title': 'Nightmarket'}), (2130, {'Title': 'Dirt'})]

Then I paired the numbers as edges, and set "statement" as edge labels. So G.edges looks like this:

[(1000, 1100, {'statement': 'boolean'}), (1100, 1110, {'statement': 'boolean'}), (1100, 1120, {'statement': 'boolean'}), (1100, 1130, {'statement': 'boolean'}), (1130, 1131, {'statement': 'boolean'}), (2000, 2100, {'statement': 'boolean'}), (2100, 2110, {'statement': 'boolean'}), (2100, 2120, {'statement': 'boolean'}), (2100, 2130, {'statement': 'boolean'})]
[(1000, 1100, {'statement': 'boolean'}), (1100, 1110, {'statement': 'boolean'}), (1100, 1120, {'statement': 'boolean'}), (1100, 1130, {'statement': 'boolean'}), (1130, 1131, {'statement': 'boolean'}), (2000, 2100, {'statement': 'boolean'}), (2100, 2110, {'statement': 'boolean'}), (2100, 2120, {'statement': 'boolean'}), (2100, 2130, {'statement': 'boolean'})]

At that point I was pretty sure that NetworkX is working fine. Now I'm gonna convert it into dot and display it. Here came the problem. It gave me this: https://i.stack.imgur.com/Dmvb3.jpg

But I'm looking for a graph like this: https://i.stack.imgur.com/wmROP.jpg

Here's my code: ("G" is the NetworkX graph that has already stored nodes and edges.)

import pydot
from IPython.display import Image

def networkx2dot(G):
    strict = nx.number_of_selfloops(G) == 0 and not G.is_multigraph()
    GDOT = pydot.Dot("OKRMAP", graph_type="digraph", strict=strict) #rankdir="LR"
    GDOT.graph_defaults = G.graph.get("graph", {})
    GDOT.set_node_defaults(shape='box', style="filled", color="black", fillcolor="white", fontname='helvetica')
    GDOT.set_edge_defaults(fontname='helvetica')
    
    for n, nodedata in G.nodes(data=True):
        if n !=None:
            str_nodedata = {k: str(v) for k, v in nodedata.items()}
            dotnode = pydot.Node(str(n), **str_nodedata)
            GDOT.add_node(dotnode)

    for u, y, edgedata in G.edges(data=True):
        if y !=None:
            str_edgedata = {k: str(v) for k, v in edgedata.items()}
            dotedge = pydot.Edge(str(u), str(y), **str_edgedata)
            GDOT.add_edge(dotedge)
    return GDOT

GDOT = networkx2dot(G)
GDOT.write_png('tmp.png')
Image('tmp.png')

I wrote this function and was trying to convert networkx graph to dot file, but somehow at somewhere something went wrong, and I couldn't figure it out.

If anyone knows how to fix this please help me. Have been stuck for three days.

1

There are 1 best solutions below

0
Ellomorce On

Ok guys....I figured it out. The key to pydot labeling is the parameter "label" in pydot.Node() and pydot.Edge()

I 've changed my function like this and it worked....

def networkx2dot(G):
strict = nx.number_of_selfloops(G) == 0 and not G.is_multigraph()
GDOT = pydot.Dot("OKRMAP", graph_type="digraph", strict=strict, resolution='96.0', size="15,15!", fontname='Microsoft JhengHei') #rankdir="LR"
GDOT.graph_defaults = G.graph.get("graph", {})
GDOT.set_node_defaults(shape='box', style="filled", color="black", fillcolor="white", fontname='Microsoft JhengHei')
GDOT.set_edge_defaults(fontname='Microsoft JhengHei', labelfontsize='10.0')

for n, nodedata in G.nodes(data=True):
    if n !=None:
        node_lst = list(nodedata.values())
        node_dict = str(node_lst[0])
        node_label = str(n)+'\n'+node_dict
        dotnode = pydot.Node(n, label = node_label)
        GDOT.add_node(dotnode)

for u, y, edgedata in G.edges(data=True):
    if y !=None:
        edge_lst = list(edgedata.values())
        edge_label = str(edge_lst[0])
        dotedge = pydot.Edge(str(u), str(y), label = edge_label)
        GDOT.add_edge(dotedge)
return GDOT

Hope this code might help.