2016-08-04 61 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