Как мне добавить новый атрибут к ребру в 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)