97

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

我需要以类似于此处显示的结构显示数据。虽然我没有子图。

我怎么能保证这样的结构?

不信者的例子:

各种 NetworkX 布局

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

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

4 回答 4

133

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

import networkx as nx
from networkx.drawing.nx_agraph import 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"
nx.nx_agraph.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=False)
plt.savefig('nx_test.png')

Graphviz 输出

NetworkX/Matplotlib 输出

更新

这是为 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')

在此处输入图像描述

于 2012-07-14T13:27:20.313 回答
10

您可以使用 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')

结果: 在此处输入图像描述

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

于 2012-07-14T02:19:59.407 回答
3

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

另外,这种可视化被称为分层图形绘制杉山式图形绘制,它可以显示多种图形,包括非树。

有关详细信息和实施,请参阅我对不同问题的回答。

于 2020-10-24T18:14:43.510 回答
0

另请参阅@Abdallah Sobehy 创建的层次结构,无需使用任何额外的模块/库(如'pygraphviz'),在 使用networkx打印python图时保留左右子节点

也许图表不如上面的那么好,但它完成了所要求的工作!

于 2021-11-09T08:51:07.967 回答