1

Having the following problem converting a networkx graph to a graphml (can't post all the code here but here is the gist). NetworkX version is 1.6.2

I have a networkx digraph called G

G = nx.DiGraph()

Populate it with weighted edges from a list of authors in the format (AuthorA, AuthorB, Weight)

G.add_weighted_edges_from(author_list)

I can export the graphml here and it works fine

nx.write_graphml(G, 'test.graphml')

I then calculate the pagerank on the graph

graph_metric = nx.pagerank_numpy(G, weight='weight')

and then add attributes to the nodes in the graph

nx.set_node_attributes(G, 'pagerank', graph_metric)

if I iterate over the graph I can print out the node name and the pagerank

for n.d in G.nodes_iter(data=True):
     print n, d

AuthorA {u'pagerank': 0.0076688948270074164} ... ... ...

but if after updating the attributes I try to create a graphml from the graph I get the following error:

File "/usr/lib/pymodules/python2.7/networkx/readwrite/graphml.py", line 111, in generate_graphml

writer.add_graph_element(G)

File "/usr/lib/pymodules/python2.7/networkx/readwrite/graphml.py", line 305, in add_graph_element

self.add_nodes(G,graph_element)

File "/usr/lib/pymodules/python2.7/networkx/readwrite/graphml.py", line 262, in add_nodes

self.add_attributes("node", node_element, data, default)

File "/usr/lib/pymodules/python2.7/networkx/readwrite/graphml.py", line 255, in add_attributes

scope=scope, default=default_value)

File "/usr/lib/pymodules/python2.7/networkx/readwrite/graphml.py", line 242, in add_data

raise nx.NetworkXError('GraphML writer does not support '

NetworkXError: GraphML writer does not support dict types as data values.

Thoughts?

Michael
  • 154
  • 3
  • 11
  • Maybe you need to post more code... I just tried it here, and it seemed to work fine. I'm py26/nx1.6 IIRC. One thing is that it is complaining that somehow, you set an attribute to a value that is a dict, which isn't valid. The above code doesn't do that, but a start would be to find out which node has an attribute with an invalid value... will post code to do that.... – Corley Brigman Jan 13 '14 at 19:15
  • I don't see anything in what you posted that looks like a problem. The error message for unsupported types was (slightly) improved in networkx-1.7 https://github.com/networkx/networkx/commit/661dcf479d9e597d6d7b83a1db7b8fbbb76f9599 so you might consider upgrading to a newer version and see if that gives a clue to what data is causing the graphml writer to complain. – Aric Jan 13 '14 at 23:39
  • You can't automatically serialize dicts when saving as GraphML. [OSMnx](http://geoffboeing.com/2016/11/osmnx-python-street-networks/) for instance has a built-in function for saving networkx networks as GraphML files, to serialize dict attributes of the nodes and edges. – eos Dec 27 '16 at 18:18

2 Answers2

1

well, it does tell you - you can't put a dictionary as a graphml attribute - they need to be either numeric types or strings, for the most part.

not the answer, but easier to put code here. find the 'bad' node:

for node in G.node:
    for attrib in G.node[node]:
        if type(G.node[node][attrib]) == dict:
            print node
Corley Brigman
  • 11,633
  • 5
  • 33
  • 40
  • It does tell you, and it is the pagerank attribute that I added - you can see from the 'AuthorA {u'pagerank': 0.0076688948270074164}'. Its odd that you can update the attributes of the node in the graph, but there is no built in way for the graphml to write them out. Seems I have to generate the graphml and then iterate back through it to update after it has been created. – Michael Jan 13 '14 at 20:13
  • did you run the code? what you are seeing is expected behaviour - that's printing `n` (which is a string) and `d` (which is an attribute dict). I get the same output, but write_graphml works fine. – Corley Brigman Jan 13 '14 at 20:20
  • 1.7. But that code didn't change much between 1.6 and 1.7 afaik. – Corley Brigman Jan 13 '14 at 20:29
  • ok....so your code prints out the attribute if its a dict, which it does - all of them. So the: nx.set_node_attributes(G, 'pagerank', graph_metric) isnt the best way to add the attribute it looks like – Michael Jan 13 '14 at 20:33
  • if any attribute is a dict value, based on the code you showed, something went wrong. what does `graph_metric` look like? it should be a simple dictionary, with the keys as the node names, and the values as the pagerank. – Corley Brigman Jan 13 '14 at 20:35
  • actually I just verified - your code doesnt print anything out. Odd. graph_metric is a dictionary of nodes with pagerank as value. Im thinking more and more that its nx.set_node_attributes causing the issue. Might just iterate through the graph and add the attributes manually then try the graphml export and see what happens. – Michael Jan 13 '14 at 20:46
  • you can verify... run the same thing after doing the `set_node_attributes` and see if it writes anything invalid. it worked here on my (tiny) dataset, but no idea what bugs you might be hitting. – Corley Brigman Jan 13 '14 at 20:50
  • and... the code only prints out nodes that have dict values, so if they are all correct, it wouldn't print anything. – Corley Brigman Jan 13 '14 at 20:51
  • ya - everything seems correct then - nothing prints. SO not sure why the write_graphml is still failing – Michael Jan 13 '14 at 20:54
  • guess it's time to fire up the debugger and see what value it thinks it has, then back-track to find it in the graph. are you sure there's no code you haven't posted? i still can't reproduce it. – Corley Brigman Jan 14 '14 at 15:08
  • No that was it. I ended up parsing through the basic graphml after it was created by networkx and adding the metric on my own. Not as fast but it looked like the networkx code to update the graphml was trying to add the whole metric dict to one node. – Michael Feb 26 '14 at 13:13
  • Anyone got a solution for this problem? I have a similar problem that I would like to solve, which is described in http://stackoverflow.com/questions/40363046/add-attributes-in-networkx-write-graphml-before-opening-in-gephi – Guido Nov 01 '16 at 15:30
0

I'm able to save GraphMl with pagerank_numpy() data:

I changed nx.set_node_attributes(G, 'pagerank', graph_metric) to nx.set_node_attributes(G, graph_metric, 'pagerank') as per the function definition in networkx doc.

I have created a graph with weight, calculated nx.pagerank_numpy() and saved GraphMl with pagerank value

Code:

import networkx as nx

G = nx.DiGraph()

G.add_edges_from([('A', 'B'), ('A', 'C'), ('B', 'G'), ('B', 'F'), ('C', 'G')], weight = 2)
G.add_edges_from([('D', 'B'), ('E', 'C'), ('E', 'F'),('B', 'H')], weight = 3)

graph_metric = nx.pagerank_numpy(G, weight='weight')
nx.set_node_attributes(G, graph_metric, 'pagerank')
nx.write_graphml(G, 'test.graphml')

GraphMl output:

<?xml version='1.0' encoding='utf-8'?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
  <key id="d1" for="edge" attr.name="weight" attr.type="int" />
  <key id="d0" for="node" attr.name="pagerank" attr.type="double" />
  <graph edgedefault="directed">
    <node id="A">
      <data key="d0">0.07114273010226772</data>
    </node>
    <node id="B">
      <data key="d0">0.16184971098265896</data>
    </node>
    <node id="C">
      <data key="d0">0.13161405068919527</data>
    </node>
    <node id="G">
      <data key="d0">0.22232103156958644</data>
    </node>
    <node id="F">
      <data key="d0">0.14068474877723428</data>
    </node>
    <node id="D">
      <data key="d0">0.07114273010226768</data>
    </node>
    <node id="E">
      <data key="d0">0.07114273010226768</data>
    </node>
    <node id="H">
      <data key="d0">0.13010226767452204</data>
    </node>
    <edge source="A" target="B">
      <data key="d1">2</data>
    </edge>
    <edge source="A" target="C">
      <data key="d1">2</data>
    </edge>
    <edge source="B" target="G">
      <data key="d1">2</data>
    </edge>
    <edge source="B" target="F">
      <data key="d1">2</data>
    </edge>
    <edge source="B" target="H">
      <data key="d1">3</data>
    </edge>
    <edge source="C" target="G">
      <data key="d1">2</data>
    </edge>
    <edge source="D" target="B">
      <data key="d1">3</data>
    </edge>
    <edge source="E" target="C">
      <data key="d1">3</data>
    </edge>
    <edge source="E" target="F">
      <data key="d1">3</data>
    </edge>
  </graph>
</graphml>
Abhi
  • 995
  • 1
  • 8
  • 12