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

上面的代码产生了以下布局,我想通过将孩子向下移动一级以与孙子水平对齐来改变它: img 显示一个根节点、五个子节点和每个子节点下的一个孙子节点


在 Python 网络库 networkx 中,我使用 graphviz 的点引擎来渲染一棵树(遵循这个建议)。我想通过指定哪些节点应该具有相同的高度来控制节点的 y 位置。节点可能位于树中的不同深度。

rank=same我知道如果我通过使用命令(例如,{rank=same; n4 -> p2;}[ ex. ])编写自己的graphviz 代码,我可以控制节点高度。但是,我依赖 networkx.graphviz_layout() [ doc | source ] 生成节点位置,graphviz_layout 只能向 pygraphviz 发送命令行参数。我尝试使用的变体nx.graphviz_layout(G, prog='dot', args="-Grank=same; n4 -> p2;")失败了。 是否可以在 pygraphviz 的 NetworkX 包装器中描述所需的节点高度,还是我需要围绕 pygraphviz 编写自己的包装器? 编辑:答案为 pygraphviz 提供了一个新的包装器。它将显着简化在 pygraphviz 的现有 NetworkX 包装器中发送排名信息的事情。如果有人能告诉我这怎么可能,我会改变我接受的答案。

4

1 回答 1

4

我找不到通过原始 networkx 包装器实现此目的的方法。

相反,我为 pygraphviz 编写了一个新的包装器,其中大部分行都是从源代码复制而来的sameRank = []它为相同等级的节点列表添加了一个参数,并for围绕pygraphviz.add_subgraph(listOfNodes,rank="same").

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"]])
于 2013-03-15T04:15:26.707 回答