以编程方式在 networkx 的 pygraphviz/dot 包装器中指定相同等级的节点

Posted

技术标签:

【中文标题】以编程方式在 networkx 的 pygraphviz/dot 包装器中指定相同等级的节点【英文标题】:Programmatically specifying nodes of the same rank within networkx's wrapper for pygraphviz/dot 【发布时间】:2013-02-27 11:39:12 【问题描述】:

是否可以更改以下代码以将 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 的点引擎来渲染一棵树(在 this recommendation 之后)。我想通过指定哪些节点应该具有相同的高度来控制节点的 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;") 的变体失败了。 是否可以在 NetworkX 包装器中为 pygraphviz 描述所需的节点高度,还是我需要围绕 pygraphviz 编写自己的包装器? 编辑: 答案提供了一个新的包装器围绕pygraphviz。它将显着简化在 pygraphviz 的现有 NetworkX 包装器中发送排名信息的事情。如果有人能告诉我这怎么可能,我会更改我接受的答案。

【问题讨论】:

【参考方案1】:

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

相反,我为 pygraphviz 编写了一个新的包装器,其中大部分行都是从 the source code 复制而来的。它为相同等级的节点列表添加了参数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)

以上是关于以编程方式在 networkx 的 pygraphviz/dot 包装器中指定相同等级的节点的主要内容,如果未能解决你的问题,请参考以下文章

改进 Python NetworkX 图形布局

标记外部节点,与networkx中的其他节点/边缘重叠最小

Textrank:使用networkx补充pagerank以进行句子提取

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

从 networkx 绘制以底图位置为中心的图形

python-networkx学习