Stefano C. Stefano C. - 2 months ago 30
Python Question

Add new attribute to an edge in networkx

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)

Answer

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