Как нарисовать DiGraph в виде организационной диаграммы?

постановление о проблеме:

Хотя мне удалось получить диаграмму из Networkx DiGraph через Matplotlib, я хотел бы получить лучшие настройки или посоветовать более подходящую библиотеку, чтобы нарисовать ее более «читабельным» способом.

Как вы увидите ниже, диаграмма довольно сильно перекошена, а края не сильно отличаются друг от друга. Это нужно исправить.


AS-IS:

список ребер и текущий график рисуются с помощью nx.kamada_kawai_layout и plt.show

список ребер:

[('D', 'N', {'fam': 2, 'weight': 3}), ('D', 'I', {'fam': 2, 'weight': 3}), ('D', 'E', {'fam': 2, 'weight': 1}), ('I', 'J', {'fam': 2, 'weight': 2}), ('L', 'M', {'fam': 2, 'weight': 2}), ('G', 'H', {'fam': 2, 'weight': 2}), ('H', 'C', {'fam': 2, 'weight': 1}), ('C', 'D', {'fam': 2, 'weight': 2}), ('C', 'K', {'fam': 2, 'weight': 1}), ('B', 'C', {'fam': 2, 'weight': 2}), ('A', 'B', {'fam': 2, 'weight': 2}), ('K', 'L', {'fam': 2, 'weight': 2}), ('E', 'F', {'fam': 2, 'weight': 2})]

список узлов:

[('D', {'fam': 2, 'leaf': 'no', 'root': 'no'}), ('N', {'fam': 2, 'leaf': 'yes', 'root': 'no'}), ('I', {'fam': 2, 'leaf': 'no', 'root': 'no'}), ('L', {'fam': 2, 'leaf': 'no', 'root': 'no'}), ('M', {'fam': 2, 'leaf': 'yes', 'root': 'no'}), ('J', {'fam': 2, 'leaf': 'yes', 'root': 'no'}), ('G', {'fam': 2, 'leaf': 'no', 'root': 'yes'}), ('H', {'fam': 2, 'leaf': 'no', 'root': 'no'}), ('C', {'fam': 2, 'leaf': 'no', 'root': 'no'}), ('B', {'fam': 2, 'leaf': 'no', 'root': 'no'}), ('A', {'fam': 2, 'leaf': 'no', 'root': 'yes'}), ('K', {'fam': 2, 'leaf': 'no', 'root': 'no'}), ('E', {'fam': 2, 'leaf': 'no', 'root': 'no'}), ('F', {'fam': 2, 'leaf': 'yes', 'root': 'no'})]

диаграмма: nx.kamada_kawai_layout

текущий код для рисования диаграммы:

elarge = [(u, v) for (u, v, d) in g.edges(data=True) if d['weight'] == 3 ]
enormal = [(u, v) for (u, v, d) in g.edges(data=True) if d['weight'] == 2 ]
esmall = [(u, v) for (u, v, d) in g.edges(data=True) if d['weight'] == 1 ]

nleaf = [(u) for (u, d) in g.nodes(data=True) if d['leaf'] == 'yes' ]
nroot = [(u) for (u, d) in g.nodes(data=True) if d['root'] == 'yes' ]

edge_labels=dict([((u,v,),d['weight']) for u,v,d in g.edges(data=True)])

pos = nx.kamada_kawai_layout(g)


# nodes
nx.draw_networkx_nodes(g, pos, node_size=200)
nx.draw_networkx_nodes(g, pos, nodelist=nleaf, node_color='g', node_size=600)
nx.draw_networkx_nodes(g, pos, nodelist=nroot, node_color='y', node_size=600)

# edges
nx.draw_networkx_edges(g, pos, edgelist=elarge, width=2, alpha=0.8, edge_color='g', style='dotted')
nx.draw_networkx_edges(g, pos, edgelist=enormal, width=2, alpha=0.8, edge_color='b', style='dashed')
nx.draw_networkx_edges(g, pos, edgelist=esmall, width=2, alpha=0.8, edge_color='b', style='solid')

# labels
nx.draw_networkx_edge_labels(g,pos,edge_labels=edge_labels)
nx.draw_networkx_labels(g, pos, font_size=10, font_family='sans-serif')


plt.axis('off')
N = 2
params = plt.gcf()
plSize = params.get_size_inches()
params.set_size_inches( (plSize[0]*N, plSize[1]*N) )
plt.show()

TO-BE

направленно, я хотел бы получить что-то вроде ниже.

примечание:

  • важна общая форма, а не цвет
  • настройка диаграммы/макета должна быть применима не только для приведенного выше примера, но и для любого DiGraph «разумного» размера (т.е. ~ 20 ребер)

орг-диаграмма как рисунок


заранее большое спасибо за ваше время и отзывы!


person ionah    schedule 03.06.2019    source источник


Ответы (1)


Вы должны использовать макет графвиза для правильной визуализации графика. Замените эту строку кода:

pos = nx.kamada_kawai_layout(g)

с этим:

pos = nx.nx_agraph.graphviz_layout(g, prog='dot')

Он использует движок DOT от graphviz, который отлично подходит для ориентированных графов, особенно DAG и деревьев. Обратите внимание, что для использования этой функции на вашем компьютере должен быть установлен Graphviz.

Я изменил ваш код draw следующим образом (влияет только на цвета/размеры):

# nodes
nx.draw_networkx_nodes(g, pos, node_size=500, node_color='#AAAAAA')
nx.draw_networkx_nodes(g, pos, nodelist=nleaf, node_color='#00BB00', node_size=800)
nx.draw_networkx_nodes(g, pos, nodelist=nroot, node_color='#9999FF', node_size=800)

# edges
nx.draw_networkx_edges(g, pos, edgelist=elarge, width=2, alpha=0.8, edge_color='g', style='dotted')
nx.draw_networkx_edges(g, pos, edgelist=enormal, width=2, alpha=0.8, edge_color='b', style='dashed')
nx.draw_networkx_edges(g, pos, edgelist=esmall, width=2, alpha=0.8, edge_color='b', style='solid')

# labels
nx.draw_networkx_edge_labels(g,pos,edge_labels=edge_labels)
nx.draw_networkx_labels(g, pos, font_size=14, font_color='w', font_family='sans-serif')

И рисует следующий график:

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

person vurmux    schedule 03.06.2019
comment
Спасибо за ваш отзыв. Диаграмма, которую вы рисуете с помощью модуля pygraphviz, полностью соответствует ожиданиям. Единственная проблема, с которой я сталкиваюсь, - это сложность установки этой библиотеки на моем бизнес-компьютере (x64 Win10 отсутствует визуальный С++ 14). Я надеюсь, что смогу справиться с этим как можно скорее. Или найти обходной путь через Palantir. - person ionah; 03.06.2019
comment
Ничего себе, я не знал, что Palantir используется за пределами США! Я уверен, что у него есть какая-то визуализация для DAG, но я не могу вам с этим помочь. Pygraphviz на Win10 x64 действительно проблема, но это единственная хорошая библиотека, которую вы можете использовать с networkx. Если это не сработает, вам придется экспортировать свой график в какой-либо формат и визуализировать его с помощью других программ, таких как Gephi. - person vurmux; 04.06.2019
comment
Привет, Вурмукс, мне удалось нарисовать график с вашим ответом в рабочей тетради по коду Palantir. Большое спасибо. - person ionah; 05.06.2019
comment
Можете ли вы дать мне свой адрес электронной почты, если вы не возражаете? Я давно интересовался Palantir, но не нашел никакой информации о Palantir Code Workbook. - person vurmux; 05.06.2019