使用 python、networkx、pygraphviz 获取图形顶点的布局坐标

Getting layout coordinates of graph vertices using python, networkx, pygraphviz

我想使用 NetworkX 创建图形,使用 Graphviz(通过 pygraphviz)布置图形。我已成功 运行 NetworkX pygraphviz examples documentation

中的所有示例

我的问题是 - 如何将顶点的坐标 (x, y) 和尺寸(宽度、高度)返回到 NetworkX 图中。 这就是目标。我只想要 Graphviz 的布局功能,而不是绘图功能。是否可以使用此堆栈(NetworkX、pygraphviz、graphviz)?还有其他方法吗?

背景动机是这样的。 Graphviz 输出 png,或 ps,或 svg 和许多其他格式。 但我不想受到 Graphviz 处理的格式的限制。 我希望能够 post- 处理布局结果,甚至 如果我最终输出像 Graphviz 支持的流行格式。

更新:为了清楚起见,我重写了问题。关于 Graphviz 输出格式的建议没有抓住重点。这是我需要的布局数据

Update2:一个建议是以某种格式制作 Graphviz 输出,然后我可以从中解析布局数据。该建议是针对 SVG 的。 我曾考虑过这种可能性。 Graphviz 输出 json(根据 Graphviz output formats documentation page)。我没能在我的 windows 安装上运行——出于某种原因,并不是所有的输出格式都存在)。然而,正是这种方法让我感到不安。为用于创建该输出的数据解析格式化输出似乎是倒退的。我认为应该提供数据本身。

更新 3 - 有一个类似的问题 - How to get the coordinates from layout from graphviz?。其中一个答案建议使用 NetworkX。但是答案使用 NetworkX 而不是 Graphviz 制作的布局。回答者不知道如何获取Graphviz布局数据。所以我的问题仍然相关,但尚未得到回答

更新 4 - 现在是 07-2019,我仍然没有找到解决这个问题的方法。我将一个答案标记为已接受 - 但有一个警告 - 尽管在该答案中找到了很好的建议,但我仍然一头雾水

迈克尔,我重新阅读了你的问题和评论,并使用我知道有效的工具(并且我知道如何使用),这就是我在你的鞋子中所做的。我会在 DOT/GraphViz 中绘制图表,然后选择一种人类可读且易于解析的格式,例如 SVG、"plain",甚至是 x-dot。为什么?不是为了获取图形本身——其中一些甚至没有实现图形——而是因为这些格式是人类可读的并且包含不同绘图组件的 X-Y 坐标。您可以根据自己的目的使用这些坐标和尺寸。我刚刚做的一个简单图表的一些片段应该可以说明。 SVG优先

<svg width="89pt" height="188pt"

<g id="node1" class="node"><title>A</title>
<ellipse fill="none" stroke="black" cx="54" cy="-162" rx="27" ry="18"/>
<text text-anchor="middle" x="54" y="-158.3" font-family="Times New Roman,serif" font-size="14.00">A</text>

或 "plain" 格式,也许最简单的解析:

graph 1 0.75 1.5
node A 0.375 1.25 0.75 0.5 A solid ellipse black lightgrey
node B 0.375 0.25 0.75 0.5 B solid ellipse black lightgrey
edge A B 4 0.375 0.99579 0.375 0.88865 0.375 0.7599 0.375 0.64045 solid black
stop

或类似 html 的 VML:

<v:oval style="position:absolute; left: 0.00; top: 0.00; width: 54.00; height: 36.00" filled="false"  >

等等...不难想象解析出各种元素的所有 X-Y 并根据需要重新调整它们的用途。

PyGraphviz 没有 API 用于检索和设置布局信息,例如节点形状、边缘路由等。我不知道这些部分的任何 Python 接口Graphviz C 库。 Graphviz 本身确实提供了一个 Python 接口,包括渲染器,但我认为它也不完全符合您的要求 - 请参阅 http://www.graphviz.org/pdf/gv.3python.pdf.

最简单的方法可能确实是按照@JHL 的建议生成 SVG。

关于更新 4

现在还是 2019 年,但这完全符合我的需要

import networkx as nx
G = nx.complete_graph(10)
pos = nx.drawing.nx_agraph.graphviz_layout(G, prog='dot')
print(pos)

给我

{0: (327.0, 666.0), 1: (504.0, 594.0), 2: (327.0, 522.0), 3: (449.0, 450.0), 4: (283.0, 378.0), 5: (283.0, 306.0), 6: (473.0, 234.0), 7: (287.0, 162.0), 8: (418.0, 90.0), 9: (287.0, 18.0)}

节点和位置的字典!

问候 dom

这是另一种解决方案。 它与 Dominik Ku​​mmer 的不同之处在于它公开了 pygraphviz.AGraph 对象,从而可以指定任意 gaphviz 属性来自定义布局。

import networkx as nx
import pygraphviz as pgv

g = nx.complete_graph(10)
ag = nx.drawing.nx_agraph.to_agraph(g)
ag.layout(prog='dot')
layout = [ag.get_node(n).attr['pos'] for n in ag.nodes()]
layout = [[int(ss) for ss in s.split(",")] for s in layout]
print(layout)

给我:

[[327, 666], [504, 594], [327, 522], [449, 450], [283, 378], [283, 306], [473, 234], [287, 162], [418, 90], [287, 18]]