[英]Python Networkx graphviz: Plot right position of nodes
I want to plot the following graph using Graphvize:我想使用 Graphvize plot 下图:
xx = nx.DiGraph()
xx.add_node("P")
xx.add_node("C0")
xx.add_node("C1")
xx.add_node("I2")
xx.add_node("C3")
xx.add_node("C4")
xx.add_node("I5")
xx.add_node("C6")
xx.add_node("C7")
xx.node["C1"]['pos'] = (2,3)
xx.node["I2"]['pos'] = (4,5)
xx.node["C3"]['pos'] = (6,7)
xx.node["C4"]['pos'] = (6,5)
xx.node["I5"]['pos'] = (4,1)
xx.node["C6"]['pos'] = (6,2)
xx.node["C7"]['pos'] = (6,0)
xx.node["P"]['pos'] = (-2,3)
xx.node["C0"]['pos'] = (0,3)
xx.add_edge("P", "C0")
xx.add_edge("C0", "C1")
xx.add_edge("C1", "I2")
xx.add_edge("I2", "C3")
xx.add_edge("I2", "C4")
xx.add_edge("C1", "I5")
xx.add_edge("I5", "C6")
xx.add_edge("I5", "C7")
layout = dict((n, xx.node[n]["pos"]) for n in xx.nodes_iter())
nx.draw(xx,pos=layout,node_color='white')
nx.write_dot(xx,'66666.dot')
With matplotlitb i geht the right position of all nodes:使用 matplotlitb,我得到了所有节点的正确 position:
With Graphviz a graph without postion.使用 Graphviz 一个没有位置的图。
My question: Is there a possibility to add the correct positions in Graphviz?我的问题:是否有可能在 Graphviz 中添加正确的位置? And is it possible to open the file "66666.dot" directly in python?是否可以直接在python中打开文件“66666.dot”?
Thank you very much for your help!非常感谢您的帮助!
Since the NetworkX library has had time to update and break backward compatibility and the problem described in the question is still in the new version of the library, I will try to update the example code for NetworkX 2.8.7 variant and provide a solution.由于NetworkX库来不及更新和打破向后兼容性,问题中描述的问题仍然存在于新版本的库中,我将尝试更新NetworkX 2.8.7变体的示例代码并提供解决方案。
NameError: name 'nx' is not defined
错误: NameError: name 'nx' is not defined
pip install.networkx
) and include the library at the beginning of the code:如何解决:这不是版本问题,这是一个最小的、可重现的示例问题,所以只需安装 NetworkX 库 ( pip install.networkx
) 并在代码开头包含该库: import.networkx as nx
AttributeError: 'DiGraph' object has no attribute 'node'
错误: AttributeError: 'DiGraph' object has no attribute 'node'
xx.nodes["C1"]['pos']
instead of xx.node["C1"]['pos']
.如何修复:使用xx.nodes["C1"]['pos']
而不是xx.node["C1"]['pos']
。 Reference: NetworkX Migration guide from 1.X to 2.0参考: 从 1.X 到 2.0 的 NetworkX 迁移指南AttributeError: 'DiGraph' object has no attribute 'nodes_iter'
错误: AttributeError: 'DiGraph' object has no attribute 'nodes_iter'
xx.nodes()
instead of xx.nodes_iter()
.如何修复:使用xx.nodes()
而不是xx.nodes_iter()
。 Reference . 参考。AttributeError: module.networkx has no attribute write_dot
错误: AttributeError: module.networkx has no attribute write_dot
nx.drawing.nx_agraph.write_dot(xx,'66666.dot')
instead of nx.write_dot(xx,'66666.dot')
.如何修复:使用nx.drawing.nx_agraph.write_dot(xx,'66666.dot')
而不是nx.write_dot(xx,'66666.dot')
。 Reference: AttributeError: 'module' object has no attribute 'write_dot' for.networkx library参考: AttributeError: 'module' object has no attribute 'write_dot' for.networkx libraryNote: If you do not already have graphviz and
pygraphviz
installed, you may need to install it.注意:如果您还没有安装graphviz和pygraphviz
,您可能需要安装它。pygraphviz
library for Windows can be installed as a precompiled binary downloaded from Unofficial Windows Binaries for Python Extension Packages with commandpip install nameOfDownloadedPackage.whl
.pygraphviz
的 pygraphviz 库可以作为从非官方 Windows 扩展包的非官方 Windows 二进制文件下载的预编译二进制文件安装,命令为pip install nameOfDownloadedPackage.whl
。
The code of the example now looks like this:该示例的代码现在如下所示:
# Listing 1
import networkx as nx
xx = nx.DiGraph()
xx.add_node("P")
xx.add_node("C0")
xx.add_node("C1")
xx.add_node("I2")
xx.add_node("C3")
xx.add_node("C4")
xx.add_node("I5")
xx.add_node("C6")
xx.add_node("C7")
xx.nodes["C1"]['pos'] = (2,3)
xx.nodes["I2"]['pos'] = (4,5)
xx.nodes["C3"]['pos'] = (6,7)
xx.nodes["C4"]['pos'] = (6,5)
xx.nodes["I5"]['pos'] = (4,1)
xx.nodes["C6"]['pos'] = (6,2)
xx.nodes["C7"]['pos'] = (6,0)
xx.nodes["P"]['pos'] = (-2,3)
xx.nodes["C0"]['pos'] = (0,3)
xx.add_edge("P", "C0")
xx.add_edge("C0", "C1")
xx.add_edge("C1", "I2")
xx.add_edge("I2", "C3")
xx.add_edge("I2", "C4")
xx.add_edge("C1", "I5")
xx.add_edge("I5", "C6")
xx.add_edge("I5", "C7")
layout = dict((n, xx.nodes[n]["pos"]) for n in xx.nodes())
nx.draw(xx,pos=layout,node_color='white')
nx.drawing.nx_agraph.write_dot(xx,'66666.dot')
TLDR: Use the format pos="x,y!"
TLDR:使用格式pos="x,y!"
to record the positions of the nodes in the file instead of pos=("x,y")
.记录文件中节点的位置而不是pos=("x,y")
。
Now that we have a workable example, we can move on to how to plot right position of nodes.现在我们有了一个可行的例子,我们可以继续讨论如何 plot 正确 position 的节点。
The created file 66666.dot
contains text in dot
language :创建的文件66666.dot
包含dot
语言的文本:
strict digraph "" {
P [pos="(-2, 3)"];
C0 [pos="(0, 3)"];
P -> C0;
C1 [pos="(2, 3)"];
C0 -> C1;
I2 [pos="(4, 5)"];
C1 -> I2;
I5 [pos="(4, 1)"];
C1 -> I5;
C3 [pos="(6, 7)"];
I2 -> C3;
C4 [pos="(6, 5)"];
I2 -> C4;
C6 [pos="(6, 2)"];
I5 -> C6;
C7 [pos="(6, 0)"];
I5 -> C7;
}
If you have graphviz installed, you can run the command in terminal:如果你安装了graphviz ,你可以在终端中运行命令:
dot -Tpng 66666.dot -o output.png
and check what will be drawn in the file output.png
:并检查将在文件output.png
中绘制的内容:
The thing is that in graphviz library there are different layout engines , which are responsible for what positions will be drawn nodes and dot
layout engine does not understand the attribute pos="(4, 1)"
, so we will use the neato
layout engine that understands this attribute (as mentioned in its documentation).问题是在 graphviz 库中有不同的布局引擎,它们负责绘制节点的位置和dot
布局引擎不理解属性pos="(4, 1)"
,所以我们将使用neato
布局引擎了解此属性(如其文档中所述)。 And we get the output in the terminal:我们在终端中得到 output:
Error: node P, position (-2, 3), expected two doubles
Error: node C0, position (0, 3), expected two doubles
Error: node C1, position (2, 3), expected two doubles
Error: node I2, position (4, 5), expected two doubles
Error: node I5, position (4, 1), expected two doubles
Error: node C3, position (6, 7), expected two doubles
Error: node C4, position (6, 5), expected two doubles
Error: node C6, position (6, 2), expected two doubles
Error: node C7, position (6, 0), expected two doubles
and file output.png
:和文件output.png
:
We see that the coordinates do not affect the drawing positions and an error is written about the incorrect format of the input data .我们看到坐标不影响绘图位置,并且会写入有关输入数据格式不正确的错误。 As mentioned there ( converting.network graph to graphviz ), this error is due to an incorrect entry of the coordinate value.正如那里提到的( converting.network graph to graphviz ),这个错误是由于坐标值输入不正确造成的。 The format that graphviz understands is pos="x,y"
, not pos="(x,y)"
. graphviz 理解的格式是pos="x,y"
,而不是pos="(x,y)"
。
Note: Full value format looks like this
%f,%f('?')?
注意:全值格式看起来像这样%f,%f('?')?
(egpos="42,24!"
). (例如pos="42,24!"
)。 The optional!
可选的!
indicates the node position should not change .指示节点 position 不应更改。
Let's change the format of positions in the graph object before writing it to the file:让我们在将图表 object 写入文件之前更改其位置格式:
# Listing 2
# See the previous part of the code in Listing 1
for node in xx:
xx.nodes[node]['pos'] = "{},{}!".format(
xx.nodes[node]['pos'][0], xx.nodes[node]['pos'][1])
nx.drawing.nx_agraph.write_dot(xx,'66666.dot')
Result in the file 66666.dot
now:现在在文件66666.dot
中生成:
strict digraph "" {
P [pos="-2,3!"];
C0 [pos="0,3!"];
P -> C0;
C1 [pos="2,3!"];
C0 -> C1;
I2 [pos="4,5!"];
C1 -> I2;
I5 [pos="4,1!"];
C1 -> I5;
C3 [pos="6,7!"];
I2 -> C3;
C4 [pos="6,5!"];
I2 -> C4;
C6 [pos="6,2!"];
I5 -> C6;
C7 [pos="6,0!"];
I5 -> C7;
}
Result in output.png
:结果为output.png
:
Looks good.看起来挺好的。 To make it look like the result from matplotlib, you need to add more attributes label
, shape
to nodes and arrowhead
to edges:为了使它看起来像 matplotlib 的结果,您需要添加更多属性label
,将shape
添加到节点,将arrowhead
添加到边缘:
# Listing 3
# See the previous part of the code in Listing 1
for node in xx:
xx.nodes[node]['pos'] = "{},{}!".format(
xx.nodes[node]['pos'][0], xx.nodes[node]['pos'][1])
xx.nodes[node]['label'] = ""
xx.nodes[node]['shape'] = "circle"
for edge in xx.edges:
xx.edges[edge]['arrowhead'] = 'box'
nx.drawing.nx_agraph.write_dot(xx,'66666.dot')
Result in output.png
:结果为output.png
:
Note (optional): To show the result of the matplotlib, add at the beginning of the file
import matplotlib.pyplot as plt
and at the endplt.show()
.注意(可选):要显示 matplotlib 的结果,请在文件开头添加import matplotlib.pyplot as plt
并在末尾plt.show()
。
.dot
file directly in Python Python中直接打开.dot
文件filename.dot
directly in Python and get a graph object, you can use function networkx.drawing.nx_agraph.read_dot
.要直接在 Python 中打开文件filename.dot
并得到图形 object,可以使用 function networkx.drawing.nx_agraph.read_dot
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.