简体   繁体   中英

"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.

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.

I've found that using arbitrary hashable nodes doesn't work with the pygraphviz backend, but it does with pydot :

import networkx as nx
from networkx.drawing.nx_pydot import graphviz_layout

g = ...
pos = graphviz_layout(g, "dot")
nx.draw_networkx(g, pos=pos)

The key point here is importing graphviz_layout from networkx.drawing.nx_pydot and not networkx.drawing.nx_agraph or elsewhere.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM