web-dev-qa-db-ja.com

networkxのEdgeに新しい属性を追加するにはどうすればよいですか?

私が持っているもの:networkxにインポートされた、ノードとエッジがgmlファイルによって読み込まれたグラフG.

問題:選択したエッジEに新しい属性を追加する方法。

やりたいこと:グラフの特定のエッジEに新しい属性「タイプ」を追加したい。注意:属性 'type'はこのEdge Eには存在しません。

私のコードは:

  G.Edge[id_source][id_target]['type']= value

しかし、Gのすべてのエッジを印刷すると、n + 1のエッジになります。 Gのすべての古いエッジと新しいエッジp =(id_source、id_target、{'type' = value})。さらに、古いEdge E(私が変更したいもの)には、新しい属性 'type'がありません。

したがって、私のコードは新しいEdgeを追加しました(私は必要ありません)。

更新したい存在しない新しい属性を追加する古いもの。

20
Stefano C.

グラフの代わりにnetworkx MultiGraphを使用している場合、エッジの属性設定は少しトリッキーです。 (ノード間に複数のエッジを持つグラフをロードすることにより、マルチグラフを取得できます)。 G.Edge[id_source][id_target]['type']= valueが必要なときに属性G.Edge[id_source][id_target][key]['type']= valueを割り当てて、データ構造を破壊している可能性があります。

以下は、グラフとマルチグラフで動作が異なる例です。

グラフの場合、属性は次のように機能します。

In [1]: import networkx as nx

In [2]: G = nx.Graph()

In [3]: G.add_Edge(1,2,color='red')

In [4]: G.edges(data=True)
Out[4]: [(1, 2, {'color': 'red'})]

In [5]: G.add_Edge(1,2,color='blue')

In [6]: G.edges(data=True)
Out[6]: [(1, 2, {'color': 'blue'})]

In [7]: G[1][2]
Out[7]: {'color': 'blue'}

In [8]: G[1][2]['color']='green'

In [9]: G.edges(data=True)
Out[9]: [(1, 2, {'color': 'green'})]

マルチグラフでは、平行エッジを追跡するためのキーの追加レベルがあるため、動作が少し異なります。キーを明示的に設定しない場合、MultiGraph.add_Edge()は、内部的に選択されたキー(連続した整数)で新しいEdgeを追加します。

In [1]: import networkx as nx

In [2]: G = nx.MultiGraph()

In [3]: G.add_Edge(1,2,color='red')

In [4]: G.edges(data=True)
Out[4]: [(1, 2, {'color': 'red'})]

In [5]: G.add_Edge(1,2,color='blue')

In [6]: G.edges(data=True)
Out[6]: [(1, 2, {'color': 'red'}), (1, 2, {'color': 'blue'})]

In [7]: G.edges(data=True,keys=True)
Out[7]: [(1, 2, 0, {'color': 'red'}), (1, 2, 1, {'color': 'blue'})]

In [8]: G.add_Edge(1,2,key=0,color='blue')

In [9]: G.edges(data=True,keys=True)
Out[9]: [(1, 2, 0, {'color': 'blue'}), (1, 2, 1, {'color': 'blue'})]

In [10]: G[1][2]
Out[10]: {0: {'color': 'blue'}, 1: {'color': 'blue'}}

In [11]: G[1][2][0]['color']='green'

In [12]: G.edges(data=True,keys=True)
Out[12]: [(1, 2, 0, {'color': 'green'}), (1, 2, 1, {'color': 'blue'})]
10
Aric

属性を1つのエッジのみに追加する理由がよくわかりません。代わりに、すべてのエッジに属性を追加してから、特定のエッジにthe wanted valueを与えることができます。

Networkxにはset_Edge_attributesというメソッドがあります。たとえば、すべてのエッジにエッジ属性を追加できます。

    G = nx.path_graph(3)
    bb = nx.Edge_betweenness_centrality(G, normalized=False)
    nx.set_Edge_attributes(G, 'betweenness', bb)
    G[1][2]['betweenness']

出力:2.0

1
Xin-Feng Li

OPの質問から追加されたソリューション:

アリックといくつかのトリックのおかげで問題を解決しました:

def add_attribute_to_Edge(H,id_node_source,id_node_target,new_attr,value_attr):

      keydict =H[id_node_source][id_node_target]
      key=len(keydict)
      for k in keydict:
          if 'type' not in H.Edge[id_source][id_target][k]:
             H.add_Edge(id_node_source,id_node_target,key=k, new_attr= value_attr)
0
TylerH

実際、新しい属性をグラフの既存のEdgeに追加するためのより良い、短い方法があります。

>>> for itr in G.edges_iter(None, True, True):
        itr

(0, 1, {})
(0, 2, {'Edge': (0, 2)})
(0, 3, {})
(0, 4, {})
(1, 2, {})
(1, 3, {})
(2, 3, {})
(2, 4, {})
(3, 4, {})
>>> G[0][1].update(Edge=(0,1))      #This will add 'Edge'=(0,1) dict item to Edge(0,1)
>>> for itr in G.edges_iter(None, True, True):
        itr


(0, 1, {'Edge': (0, 1)})
(0, 2, {'Edge': (0, 2)})
(0, 3, {})
(0, 4, {})
(1, 2, {})
(1, 3, {})
(2, 3, {})
(2, 4, {})
(3, 4, {})
0
Vibhor Mishra

Xin-Feng Liによる以下の回答は機能します。valuesnameの引数がNetworkx v1.x(回答が最初に書かれたとき)とNetworkx v2.xの間で切り替わったことに注意してください。 v2.xの場合、コードは次のとおりです。

G = nx.path_graph(3)
bb = nx.Edge_betweenness_centrality(G, normalized=False)
nx.set_Edge_attributes(G, bb, 'betweenness')
G[1][2]['betweenness']
0
scorch421