Как мне добавить новый атрибут к ребру в networkx?

Что у меня есть: график G, импортированный в networkx с узлами и ребрами, загруженными gml файлом.

Проблема: как добавить новый атрибут к выбранному ребру E.

Что я хочу сделать: Я хочу добавить новый атрибут 'type' для определенного ребра E моего графика. Внимание: атрибут 'type' не существует для этого ребра E.

Мой код:

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

Но если я напечатаю все ребра G, теперь у меня будет n + 1 ребер; все старые ребра G и новое ребро p = (id_source, id_target, {'type' = value}). Кроме того, у старого ребра E (которое я хочу изменить) нет нового атрибута "тип".

Таким образом, мой код добавил новое преимущество (которое мне не нужно).

Я хочу обновить старый, добавив новый атрибут, который не существует.

Ответ 1

У вас может быть networkx MultiGraph вместо графика, и в этом случае настройка атрибута для ребер немного сложнее. (Вы можете получить мультиграфию, загрузив граф с несколькими границами между узлами). Возможно, вы повреждаете структуру данных, назначая атрибут  G.edge[id_source][id_target]['type']= value, когда вам нужно   G.edge[id_source][id_target][key]['type']= value.

Вот примеры того, как это работает по-разному для Graphs и MultiGraphs.

Для атрибутов case Graph работают следующим образом:

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

С MultiGraphs имеется дополнительный уровень клавиш для отслеживания параллельных ребер, поэтому он работает несколько иначе. Если вы не указали явным образом ключ MultiGraph.add_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'})]

Ответ 2

Я не совсем понимаю, почему вы хотите добавить атрибут только к одному ребру, вместо этого вы можете добавить атрибут ко всем ребрам, а затем придать 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

Ответ 3

На самом деле есть лучший и короткий способ добавления новых атрибутов к существующему ребру в графе:

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

Ответ 4

Приведенный ниже ответ Синь-Фэна Ли работает, просто отметьте, что аргументы для values и name переключались между 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']

Ответ 5

Решение добавлено из 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)