2016-08-04 30 views
0

我有一个网络要输出到json文件。但是,当我输出它时,节点目标将转换为数字,并且不匹配字符串的节点ID。目标与networkx json文件中的节点ID不匹配

例如:

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

结果:

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

在python。这是对的。

但在输出端,当我写出像这样的数据...

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

而IDS三个目标节点的STR1',“str2的”和“STR3” ...

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

节点22的目标已经变成了数字

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

出现这种情况有字符串ID的所有节点s

这是怎么回事,我该如何预防呢?

期望的结果是,“目标”字段应该保留字符串ID,或者字符串ID以匹配目标的方式变成数字。

回答

1

这是为什么

这是一个特点。并非所有的图库都接受字符串作为标识符,但我所知道的所有接受整数。

我该如何预防?

使用nodes地图由节点名称更换IDS:

>>> 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'}]} 
+0

啊有趣的是,它似乎是如果字符串被替换为链接目标和来源的数字,那么应该是ID值 - 否则库如何从输出json数据知道节点连接到什么?我想我对networkx和图形是新手,所以涉及的所有问题都不清楚。 尽管如此,感谢您的答案,以及如何访问和修改这些数据:) – CHP

+0

“id值”是什么意思?整数节点名称?它们也被替换。例如,在'links'数组中,''source':0'指向节点0,它被命名为1. –

+0

我的意思是说,当我使用json_graph.node_link_data写出数据时,它将使得像'节点'和'链接'。在“节点”下,替换不会发生,仅在“链接”下。但是我想你会说所有独特的“源”值都等价于需要连接的节点列表,所以如果读取数据的软件忽略了“节点”键而只是使用“源'数据。 – CHP

0

使输出符合该是node_link_data文档中链接的D3模板,你可以对几个简单的变化node_link_data函数。只需运行下面的函数并使用它。我所做的只是修改模板的一些不必要的输出,并存储图形标签而不是索引。用于目标和目标的原始函数的索引是在函数中创建的,因此它不是可以从图形本身提取的东西,所以如果您想确定节点标签对应于链接,最安全的方法是修改node_link_data。

The D3 Template this creates data for is here

请注意,如果您使用以下数据不添加节点或链路属性,你将需要删除的D3模板下面几行:

.attr("stroke-width", function(d) { return Math.sqrt(d.value); }) 

.attr("fill", function(d) { return color(d.group); }) 

修改功能:

from itertools import chain, count 
import json 
import networkx as nx 
from networkx.utils import make_str 
__author__ = """Aric Hagberg <[email protected]>""" 
_attrs = dict(id='id', source='source', target='target', key='key') 

def node_link_data(G, attrs=_attrs): 
    """Return data in node-link format that is suitable for JSON serialization 
    and use in Javascript documents. 
    """ 
    multigraph = G.is_multigraph() 
    id_ = attrs['id'] 
    source = attrs['source'] 
    target = attrs['target'] 
    # Allow 'key' to be omitted from attrs if the graph is not a multigraph. 
    key = None if not multigraph else attrs['key'] 
    if len(set([source, target, key])) < 3: 
     raise nx.NetworkXError('Attribute names are not unique.') 
    mapping = dict(zip(G, count())) 
    data = {} 
    data['nodes'] = [dict(chain(G.node[n].items(), [(id_, n)])) for n in G] 
    if multigraph: 
     data['links'] = [ 
      dict(chain(d.items(), 
         [(source, u), (target,v), (key, k)])) 
      for u, v, k, d in G.edges_iter(keys=True, data=True)] 
    else: 
     data['links'] = [ 
      dict(chain(d.items(), 
         [(source, u), (target, v)])) 
      for u, v, d in G.edges_iter(data=True)] 
    return data