Вывод меток ребер из графика

#python-3.x #networkx

#python-3.x #networkx

Вопрос:

Есть ли встроенная функция для добавления меток ребер к графику в networkx библиотеке. AFAIK вы можете установить их с помощью nx.set_edge_attributes() функции. Но мне было интересно, можно ли было бы пропустить это и избежать выполнения вручную, если у вас уже есть информация о метках ребер в вашей структуре графика.

Например, учитывая следующий словарь словарей, в котором ключами являются узлы, а внутренними словарями являются метки цели и края соответственно. Например:

 z = {'224': {'0': 'a'}, '0': {'217': 'b', '224': 'k'}, '217': {'220': 'c'}, '246': {'10': 'd'}, '10': {'241': 'f', '246': 'l'},
 '241': {'220': 'g'}, '11': {'22': 'p', '23': 'i'}, '22': {'9': 'p'}}
  

В приведенном выше словаре ‘224 будет узлом, подключенным к ‘0’ с меткой ‘a’.

Я знаю, что могу создать график с помощью:

 Z = nx.DiGraph(z)
  

И построить его с помощью:

 pos = nx.spring_layout(Z)
nx.draw(Z, pos, with_labels=True, font_weight='bold')
  

Я попытался добавить метки вручную из z, но не смог уловить случай, когда узел подключен к более чем одному узлу со своей собственной пограничной меткой, по крайней мере, как ожидалось.

То, что я пробовал до сих пор, было:

 edge_labels = dict()
for (k, v), e in zip(z.items(), Z.edges()):
    for x, y in v.items():
        edge_labels[e] = {'attr1': y}
  

А затем добавьте эти метки с помощью:

 nx.set_edge_attributes(Z, edge_labels)
  

Но сбой и выдает следующий неправильный вывод при просмотре ребер с помощью Z.edges(data=True) :

 Out[38]: OutEdgeDataView([('224', '0', {'attr1': 'a'}), ('0', '217', {'attr1': 'k'}), ('0', '224', {'attr1': 'c'}), ('217', '220', {'attr1': 'd'}), ('246', '10', {'attr1': 'l'}), ('10', '241', {'attr1': 'g'}), ('10', '246', {'attr1': 'i'}), ('241', '220', {'attr1': '8'}), ('11', '22', {}), ('11', '23', {}), ('22', '9', {})])
  

Я упускаю здесь что-то очевидное?

Ожидаемый результат должен выглядеть следующим образом:

 Out[39]: OutEdgeDataView([('224', '0', {'attr1': 'a'}), ('0', '217', {'attr1': 'b'}), ('0', '224', {'attr1': 'k'}), ('217', '220', {'attr1': 'c'}), ('246', '10', {'attr1': 'd'}), ('10', '241', {'attr1': 'f'}), ('10', '246', {'attr1': 'l'}), ('241', '220', {'attr1': 'g'}), ('11', '22', {'attr1': 'p'}), ('11', '23', {'attr1': 'i'}), ('22', '9', {'attr1': 'p'})])
  

Ответ №1:

networkx имеет функцию draw_networkx_edge_labels, которая позволяет вам рисовать метки графика. Но это не базовая функциональность graphs, поэтому ее использование немного сбивает с толку:

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

 import networkx as nx

# Create graph
G = nx.DiGraph()
G.add_nodes_from([1,2,3,4,5])
G.add_edges_from([(1,2),(2,3),(2,4),(4,5)])
for n in G.nodes:
    G.nodes[n]['label'] = str(n)*5

# Create labels dicts
labels = {
    n: (G.nodes[n]['label']
        if len(list(nx.all_neighbors(G, n))) > 2
        else '')
    for n in G.nodes
}
edge_labels = {e: str(e) for e in G.edges}

# Create graph layout
layout = nx.spring_layout(G)

# Create label edges
edge_labels_pos = nx.draw_networkx_edge_labels(
    G,
    layout,
    edge_labels=edge_labels
)

# Draw the graph
nx.draw(G, with_labels=True, labels=labels, pos=layout)
  

Результат будет выглядеть так:

введите описание изображения здесь

Но не забудьте заранее создать макет и использовать его везде! Если вы вызовете функции компоновки несколько раз, вы получите что-то вроде этого:

введите описание изображения здесь