Search code examples
pythonnetworkxpygraphviz

"KeyError: Node not in graph" when using pygraphviz_layout even though node is in networkx graph


I have a DataFrame network_df consisting of an edge list

G = nx.from_pandas_edgelist(network_df,source='Parent Node',target= 'Child Node',create_using=nx.DiGraph())

I'm using pygraphviz_layout to calculate the position of each node in G

  pos = pygraphviz_layout(G,prog="dot", args='-Gnodesep=10-Goverlap=false')

But this raises the following error:

Exception has occurred: KeyError
Traceback (most recent call last):
 File "C:\..\Python37\lib\site-packages\pygraphviz\agraph.py", line 1615, in __new__
  nh = gv.agnode(graph.handle, n.encode(graph.encoding), _Action.find)
  KeyError: 'agnode: no key'

  During handling of the above exception, another exception occurred:

  Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\...\Python37\lib\site-packages\networkx\drawing\nx_agraph.py", 
  line 293, in pygraphviz_layout
  node = pygraphviz.Node(A, n)
  File "C:\...\Python37\lib\site- 
  packages\pygraphviz\agraph.py", line 1617, in __new__
    raise KeyError("Node %s not in graph." % n)

  KeyError: "Node ('', '', 'A /// Standard', 'Event A') not in graph."

But when I do

key = ('', '', 'A /// Standard', 'Event A')
print(key in G.nodes())

This prints True meaning that the node is indeed in the Graph, what can I be doing wrong here?

Also, if I use some other function to calculate the position, it works

pos = nx.spring_layout(G)

What is wrong here? pygraphviz_layout has worked without any problems before for other datasets.


Solution

  • The following should work:

    import networkx as nx
    
    # an example graph with string (names) as nodes
    g = nx.les_miserables_graph()
    
    
    labels_to_int = {}
    int_to_labels = {}
    for i, label in enumerate(g):
        labels_to_int[label] = i
        int_to_labels[i] = label
    
    # update labels to ints with
    nx.relabel_nodes(g, labels_to_int, copy=False)
    print(g.nodes)
    # Tested only with the following since I have pygraphviz not installed 
    pos = nx.kamada_kawai_layout(g)
    # pos = pygraphviz_layout(G,prog="dot", args='-Gnodesep=10-Goverlap=false')
    
    # changes back to original labels
    nx.relabel_nodes(g, int_to_labels, copy=False)
    
    label_pos = {label: pos[labels_to_int[label]] for label in g}
    print(label_pos)
    # {'Napoleon': array([0.73407672, 0.66096404]), 'Myriel': array([0.67744174, 0.53499379]), ....
    print(g.nodes)
    # ['Napoleon', 'Myriel', ...
    

    Background

    The reason for you error is probably that pygraphviz cannot work with arbitrary (hashable) nodes unlike networkx. Therefore, above code simply cast the node labels to int before calling the layout and revert the changes in the nodes and the pos dict.