CHP CHP - 3 months ago 13
Python Question

Targets don't match node IDs in networkx json file

I have a network I want to output to a json file. However, when I output it, node targets become converted to numbers and do not match the node ids which are strings.

For example:

G = nx.DiGraph(data)
G.edges()


results in:

[(22, 'str1'),
(22, 'str2'),
(22, 'str3')]


in python. This is correct.

But in the output, when I write out the data like so...

json.dump(json_graph.node_link_data(G), f,
indent = 4, sort_keys = True, separators=(',',':'))


while the ids for the three target nodes 'str1', 'str2', and 'str3'...

{
"id":"str1"
},
{
"id":"str2"
},
{
"id":"str3"
}


The targets of node 22 have been turned into numbers

{
"source":22,
"target":972
},
{
"source":22,
"target":1261
},
{
"source":22,
"target":1259
}


This happens for all nodes that have string ids

Why is this, and how can I prevent it?

The desired result is that either "target" fields should keep the string ids, or that the string ids become numeric in a way that they match the targets.

Answer

Why is this

It's a feature. Not all graph libraries accept strings as identifiers, but all that I know of accept integers.

how can I prevent it?

Replace the ids by node names using the nodes map:

>>> import networkx as nx
>>> import pprint
>>> g = nx.DiGraph()
>>> g.add_edge(1, 'foo')
>>> g.add_edge(2, 'bar')
>>> g.add_edge('foo', 'bar')
>>> res = nx.node_link_data(g)
>>> pprint.pprint(res)
{'directed': True,
 'graph': {},
 'links': [{'source': 0, 'target': 3},
           {'source': 1, 'target': 2},
           {'source': 3, 'target': 2}],
 'multigraph': False,
 'nodes': [{'name': 1}, {'name': 2}, {'name': 'bar'}, {'name': 'foo'}]}
>>> res['links'] = [
        {
            'source': res['nodes'][link['source']]['name'],
            'target': res['nodes'][link['target']]['name']
        }
        for link in res['links']]
>>> pprint.pprint(res)
{'directed': True,
 'graph': {},
 'links': [{'source': 1, 'target': 'foo'},
           {'source': 2, 'target': 'bar'},
           {'source': 'foo', 'target': 'bar'}],
 'multigraph': False,
 'nodes': [{'name': 1}, {'name': 2}, {'name': 'bar'}, {'name': 'foo'}]}