Край Networkx неправильно добавляет атрибуты

Я поднял некоторый код, с которым я играл в 1.6.1 сети x. На 1.8.1 не работает при записи в gml или же graphml,

Проблема сводится к невозможности записать атрибуты ребра внутри данных, например:

BasicGraph = nx.read_graphml("KeggCompleteEng.graphml")

for e,v in BasicGraph.edges_iter():
    BasicGraph[e][v]['test'] = 'test'

nx.write_graphml(BasicGraph, "edgeTester.graphml")

Вызывает ошибку:

AttributeError: 'str' object has no attribute 'items'

Когда я использую: for e,v,data in BasicGraph.edges_iter(data=True): данные выводятся так:

{'root_index': -3233, 'label': u'unspecified'}
test

AKA новый атрибут находится вне словаря.

Документация говорит, что я должен быть в состоянии сделать это, как указано выше. Тем не менее, я полагаю, что совершил глупую ошибку и был бы признателен за возвращение на правильный путь!

РЕДАКТИРОВАТЬ:

Итак, я запустил программу с графиком, сгенерированным внутри программы: BasicGraph = nx.complete_graph(100) и все прошло нормально.

Затем я запустил его с примером файла graphml из учебника: BasicGraph = nx.read_graphml("graphmltest.graphml") и это тоже сработало. (Я даже импортировал в и из Cytoscape, чтобы проверить, что это не проблема)

Очевидно, это файл, который я использую. Вот ссылка на него, кто-нибудь может увидеть, что с ним не так?

1 ответ

Решение

Проблема в том, что ваш график имеет параллельные ребра, поэтому NetworkX загружает его как объект MultiGraph:

In [1]: import networkx as nx

In [2]: G = nx.read_graphml('KeggCompleteEng.graphml')

In [3]: type(G)
Out[3]: networkx.classes.multigraph.MultiGraph

In [4]: G.number_of_edges()
Out[4]: 7123

In [5]: H = nx.Graph(G) # convert to graph, remove parallel edges

In [6]: H.number_of_edges()
Out[6]: 6160

Из-за этого внутренняя структура хранилища графического объекта для ребра имеет вид G[узел][узел][ключ][атрибут]= значение (обратите внимание на дополнительный словарный уровень для мультиграфов).

Вы явно модифицируете структуру

for e,v in BasicGraph.edges_iter():
    BasicGraph[e][v]['test'] = 'test'

который ломает это.

Разрешается изменять структуру данных таким образом, но безопаснее использовать API-интерфейс NetworkX.

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

In [8]: G.add_edge(1,2,key='one')

In [9]: G.add_edge(1,2,key='two')

In [10]: G.edges(keys=True)
Out[10]: [(1, 2, 'two'), (1, 2, 'one')]

In [11]: G.add_edge(1,2,key='one',color='red')

In [12]: G.add_edge(1,2,key='two',color='blue')

In [13]: G.edges(keys=True,data=True)
Out[13]: [(1, 2, 'two', {'color': 'blue'}), (1, 2, 'one', {'color': 'red'})]
Другие вопросы по тегам