如何以组织图的方式绘制DiGraph?

时间:2019-06-03 09:14:55

标签: python matplotlib networkx pygraphviz digraphs

问题陈述:

虽然我通过Matplotlib设法从Networkx DiGraph中获得了图表,但我希望我可以得到更好的设置或被建议使用更合适的库以更“可读”的方式绘制图表。

正如您将在下面看到的那样,图表几乎是歪斜的,并且边缘彼此之间的区别也不大。这需要纠正。


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()

待办事项

定向,我想得到类似下面的内容。

注意:

  • 重要的是整体形状,而不是颜色
  • 图表/布局设置不仅应适用于上面提供的示例,而且还应适用于任何“合理”大小(即约20个边距)的DiGraph

org-chart like drawing


非常感谢您的时间和反馈!

1 个答案:

答案 0 :(得分:1)

您应该使用graphviz layout进行正确的图形可视化。替换此行代码:

pos = nx.kamada_kawai_layout(g)

与此:

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

它使用来自graphviz的DOT引擎,这对于有向图(尤其是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')

并绘制以下图形:

enter image description here