有没有办法保证NetworkX的分层输出?

时间:2012-07-13 23:32:02

标签: python networkx

我正在尝试生成结构的流程图。我已经能够使用networkx创建代表性图形,但是当我输出绘图时,我需要一种方法来显示结构。我正在使用matplotlib.pylab绘制图表。

我需要在类似于显示here的结构中显示数据。虽然我没有子图。

我如何保证这样的结构?

不信之人的例子:

Various NetworkX layouts

我已经能够使用pylab和graphviz显示图形,但都没有提供我正在寻找的树结构。我尝试过网络必须提供的每个布局,但没有一个显示层次结构。如果我需要使用权重,我只是不确定选项/模式给它 OR 。任何建议都会有所帮助。

@jterrace:

这是我用来制作上图的粗略轮廓。我添加了一些标签,但除此之外它是相同的。

import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()

G.add_node("ROOT")

for i in xrange(5):
    G.add_node("Child_%i" % i)
    G.add_node("Grandchild_%i" % i)
    G.add_node("Greatgrandchild_%i" % i)

    G.add_edge("ROOT", "Child_%i" % i)
    G.add_edge("Child_%i" % i, "Grandchild_%i" % i)
    G.add_edge("Grandchild_%i" % i, "Greatgrandchild_%i" % i)

plt.title("draw_networkx")
nx.draw_networkx(G)

plt.show()

3 个答案:

答案 0 :(得分:89)

如果您使用有向图,那么Graphviz点布局将使用树执行您想要的操作。以下是一些类似于上述解决方案的代码,显示了如何执行此操作

import networkx as nx
import matplotlib.pyplot as plt
G = nx.DiGraph()

G.add_node("ROOT")

for i in xrange(5):
    G.add_node("Child_%i" % i)
    G.add_node("Grandchild_%i" % i)
    G.add_node("Greatgrandchild_%i" % i)

    G.add_edge("ROOT", "Child_%i" % i)
    G.add_edge("Child_%i" % i, "Grandchild_%i" % i)
    G.add_edge("Grandchild_%i" % i, "Greatgrandchild_%i" % i)

# write dot file to use with graphviz
# run "dot -Tpng test.dot >test.png"
nx.write_dot(G,'test.dot')

# same layout using matplotlib with no labels
plt.title('draw_networkx')
pos=nx.graphviz_layout(G, prog='dot')
nx.draw(G, pos, with_labels=False, arrows=False)
plt.savefig('nx_test.png')

Graphviz output

NetworkX/Matplotlib output

<强>已更新

这是针对networkx-2.0更新的版本(以及即将推出的networkx-2.1绘制箭头)。

import networkx as nx
from networkx.drawing.nx_agraph import write_dot, graphviz_layout
import matplotlib.pyplot as plt
G = nx.DiGraph()

G.add_node("ROOT")

for i in range(5):
    G.add_node("Child_%i" % i)
    G.add_node("Grandchild_%i" % i)
    G.add_node("Greatgrandchild_%i" % i)

    G.add_edge("ROOT", "Child_%i" % i)
    G.add_edge("Child_%i" % i, "Grandchild_%i" % i)
    G.add_edge("Grandchild_%i" % i, "Greatgrandchild_%i" % i)

# write dot file to use with graphviz
# run "dot -Tpng test.dot >test.png"
write_dot(G,'test.dot')

# same layout using matplotlib with no labels
plt.title('draw_networkx')
pos =graphviz_layout(G, prog='dot')
nx.draw(G, pos, with_labels=False, arrows=True)
plt.savefig('nx_test.png')

enter image description here

答案 1 :(得分:7)

您可以使用pygraphviz来关闭:

>>> import pygraphviz
>>> import networkx
>>> import networkx as nx
>>> G = nx.Graph()
>>> G.add_node("ROOT")
>>> for i in xrange(5):
...     G.add_node("Child_%i" % i)
...     G.add_node("Grandchild_%i" % i)
...     G.add_node("Greatgrandchild_%i" % i)
...     G.add_edge("ROOT", "Child_%i" % i)
...     G.add_edge("Child_%i" % i, "Grandchild_%i" % i)
...     G.add_edge("Grandchild_%i" % i, "Greatgrandchild_%i" % i)

>>> A = nx.to_agraph(G)
>>> A.layout('dot', args='-Nfontsize=10 -Nwidth=".2" -Nheight=".2" -Nmargin=0 -Gfontsize=8')
>>> A.draw('test.png')

结果: enter image description here

注意我从上面发布的链接中复制了graphviz选项。我不确定为什么第四个孩子被画在上面而不是严格的垂直格式。也许对Graphviz选项有更多了解的人可以提供帮助。

答案 2 :(得分:0)

如果您不想安装graphviz,则可以将grandalf用于仅限python的解决方案。

此外,这种可视化类型称为layered graph drawingSugiyama-style graph drawing,它们可以显示多种图形,包括非树。

有关详细信息和实现,请参见my answer to a different question