使用networkx对pygraphviz/dot进行包装时,如何以编程方式指定同一级别的节点

6

是否有可能修改以下代码,使Child_4与Grandchild_0处于同一水平线上(从而将Grandchild_4推到其自己的层次)?

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_edge("ROOT", "Child_%i" % i)
    G.add_edge("Child_%i" % i, "Grandchild_%i" % i)

pos=nx.graphviz_layout(G,prog='dot')
nx.draw(G,pos,arrows=False)
plt.show()

上面的代码生成了以下布局,我想通过将一个子元素向下移动一级以与孙元素水平对齐来修改它: 图片显示了一个根节点,五个子节点和每个子节点下面只有一个孙节点
在Python网络库networkx中,我正在使用graphviz的dot引擎来渲染树(遵循this recommendation)。我想通过指定应该具有相同高度的节点来控制节点的y位置。这些节点可能位于树的不同深度。
我知道如果我编写自己的graphviz代码并使用rank=same命令(例如,{rank=same; n4 -> p2;} [ex.]),我可以控制节点高度。但是,我依赖于networkx.graphviz_layout() [doc | source]生成节点位置,而graphviz_layout只能向pygraphviz发送命令行参数。我尝试使用nx.graphviz_layout(G, prog='dot', args="-Grank=same; n4 -> p2;")的变体,但失败了。如何在NetworkX包装器中描述所需的节点高度?或者我需要编写自己的pygraphviz包装器吗?编辑:答案提供了一个新的pygraphviz包装器。如果有人能告诉我如何在现有的NetworkX pygraphviz包装器中发送排名信息,那将极大地简化事情。
1个回答

4
我无法通过原始的networkx包找到实现这一点的方法。
相反,我编写了一个新的pygraphviz包装器,其中大部分代码都是从源代码中复制而来。它添加了一个参数sameRank = []用于存储同一排节点列表,并在调用pygraphviz.add_subgraph(listOfNodes,rank="same")时添加了一个for循环。
def graphviz_layout_with_rank(G, prog = "neato", root = None, sameRank = [], args = ""):
    ## See original import of pygraphviz in try-except block
    ## See original identification of root through command line
    A = nx.to_agraph(G)
    for sameNodeHeight in sameRank:
        if type(sameNodeHeight) == str:
            print("node \"%s\" has no peers in its rank group" %sameNodeHeight)
        A.add_subgraph(sameNodeHeight, rank="same")
    A.layout(prog=prog, args=args)
    ## See original saving of each node location to node_pos 
    return node_pos

在这个问题的例子中,通过以下行代码,可以将Child_4推到与Grandchild_0相同的水平级别:
pos=graphviz_layout_with_rank(G, prog='dot',sameRank=[["Child_4","Grandchild_0"]])

如果有人遇到“module 'networkx' has no attribute 'to_agraph'”错误,请使用“A = nx.nx_agraph.to_agraph(G)”而不是“A = nx.to_agraph(G)”。 - Ahmed Karaman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接