Add new attribute to an edge in networkx

2019-02-03 06:08发布

问题:

What i Have: a graph G imported in networkx whit nodes and egdes loaded by gml file.
Problem : How to add a new attribute to a selected edge E.
What i want to do: i want to add a new attribute 'type' for a particular edge E of my graph. Attention: the attribute 'type' doesn't exist for this edge E.

I read a lot of solutions proposed in Internet and here, but no one of those solutions solves my problem. In fact my code is:

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

But if i print all the edges of G, now i have n+1 edges, all the old edges of G, and a new edge p= (id_source, id_target, {'type'= value}). Furthermore, the old edge E (the one that i want modify) doesn't have the new attribute 'type'.

So my code have added a new edge (that i don't want).
I want update the old one adding a new attribute that doesn't exist.

Thank you for your help !

EDIT: SOLVED Thanks to Aric and some tricks i solved my problem:

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)

回答1:

You may have a networkx MultiGraph instead of a graph and in that case the attribute setting for edges is a little tricker. (You can get a multigraph by loading a graph with more than one edge between nodes). You may be corrupting the data structure by assigning the attribute G.edge[id_source][id_target]['type']= value when you need G.edge[id_source][id_target][key]['type']= value.

Here are examples of how it works differently for Graphs and MultiGraphs.

For the Graph case attributes work like this:

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'})]

With MultiGraphs there is an additional level of keys to keep track of the parallel edges so it works a little differently. If you don't explicitly set a key MultiGraph.add_edge() will add a new edge with an internally chosen key (sequential integers).

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'})]


回答2:

I don't quite understand why you want add an attribute to only one edge, instead you can add an attribute to all edges, then you give the the wanted value to your specific edge.

Networkx has a method called set_edge_attributes can add an edge attributes to all edges, for example

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

Output: 2.0



回答3:

Actually, there is a better and short way to add new attributes to an existing edge in a graph:

>>> 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, {})