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

Posted

技术标签:

【中文标题】有没有办法保证 NetworkX 的分层输出?【英文标题】:Is there a way to guarantee hierarchical output from NetworkX? 【发布时间】:2012-07-13 20:14:50 【问题描述】:

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

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

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

不信者的例子:

我已经能够使用 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()

【问题讨论】:

【参考方案1】:

如果您使用有向图,那么 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')

更新

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

【讨论】:

啊哈!所以我需要的只是一个带有“点”布局的有向图。我知道这是非常小的东西。非常感谢阿里克! 有什么好的方法可以升序标记节点吗?我的意思是,我创建一个图形 g = nx.full_rary_tree(2, 10) 如果我打印我得到的边:[(0, 1), (0, 2), (1, 3), (1, 4), (2, 5), ... ] 但它会以不同的顺序将它们可视化...... PyGrapviz 适用于 Python 3,此代码适用于 Python 3。 另外,如果您在常规方式安装pygraphviz 时遇到任何问题,请尝试pip install --install-option="--include-path=/usr/local/include/" --install-option="--library-path=/usr/local/lib/" pygraphviz @Rotail 在我安装了graphviz(在我的情况下使用brew install graphviz)之后,这对我有用。【参考方案2】:

你可以使用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 -N -N -Nmargin=0 -Gfontsize=8')
>>> A.draw('test.png')

结果:

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

【讨论】:

谢谢。这正是我尝试时所看到的。我觉得它为什么会产生这样的东西有点奇怪。 请注意,在 networkx 的 1.11 版本中,api 发生了变化。 to_agraph 函数现在位于 nx.nx_agraph.to_agraph 有没有办法确保孩子总是低于父母?【参考方案3】:

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

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

有关详细信息和实施,请参阅my answer to a different question。

【讨论】:

【参考方案4】:

另请参阅@Abdallah Sobehy 创建的层次结构,无需使用任何额外的模块/库(如“pygraphviz”),位于 preserving the left and right child while printing python graphs using networkx

也许这个图表没有上面的那么好,但它完成了所要求的工作!

【讨论】:

以上是关于有没有办法保证 NetworkX 的分层输出?的主要内容,如果未能解决你的问题,请参考以下文章

如何为我的 networkx 图指定精确的输出大小?

networkx:绘制多方图时的节点间距

如何在 Python 中重塑 networkx 图?

节点作为networkx中的格点

使用networkX输出树形结构

添加边缘权重以在 networkx 中绘制输出