[英]Drawing labels that follow their edges in a Networkx graph
Working with Networkx, I have several edges that need to be displayed in different ways.使用 Networkx,我有几个需要以不同方式显示的边。 For that I use the connectionstyle, some edges are straight lines, some others are Arc3.为此,我使用了连接样式,有些边是直线,有些是 Arc3。 The problem is that every edge has a label and the label doesn't follow the edges in these styles.问题是每条边都有一个标签,并且标签不跟随这些样式中的边。
I borrowed a graph as example :我借了一张图作为例子:
#!/usr/bin/env python3
import networkx as nx
import matplotlib.pyplot as plt
# Graph data
names = ['A', 'B', 'C', 'D', 'E']
positions = [(0, 0), (0, 1), (1, 0), (0.5, 0.5), (1, 1)]
edges = [('A', 'B'), ('A', 'C'), ('A', 'D'), ('A', 'E'), ('D', 'A')]
# Matplotlib figure
plt.figure('My graph problem')
# Create graph
G = nx.MultiDiGraph(format='png', directed=True)
for index, name in enumerate(names):
G.add_node(name, pos=positions[index])
labels = {}
for edge in edges:
G.add_edge(edge[0], edge[1])
labels[(edge[0], edge[1])] = '{} -> {}'.format(edge[0], edge[1])
layout = dict((n, G.node[n]["pos"]) for n in G.nodes())
nx.draw(G, pos=layout, with_labels=True, node_size=300, connectionstyle='Arc3, rad=0.3')
nx.draw_networkx_edge_labels(G, layout, edge_labels=labels, connectionstyle='Arc3, rad=0.3')
# Here is the problem : the labels will not follow the edges
plt.show()
That can lead to problems as shows this example image : we're not sure for which edge is the label.这可能会导致问题,如本示例图像所示:我们不确定哪个边缘是标签。
Is there a way to draw labels that follow their edges ?有没有办法绘制跟随其边缘的标签?
Thanks谢谢
Yes, it is possible to draw labeled edges of networkx
directed graphs, by using GraphViz.是的,可以使用 GraphViz 绘制networkx
向图的标记边。 An example using the Python package graphviz
, the Python package networkx
, and the GraphViz program dot
:使用 Python 包graphviz
、Python 包networkx
和GraphViz程序dot
的示例:
"""How to draw a NetworkX graph using GraphViz.
Requires:
- The Python package `graphviz`: https://github.com/xflr6/graphviz
`pip install graphviz`
- The Python package `networkx`: https://github.com/xflr6/graphviz
`pip install networkx`
- The GraphViz program `dot` in the environment's path
https://graphviz.org/download/
https://en.wikipedia.org/wiki/PATH_(variable)
"""
import graphviz as gv
import networkx as nx
def dump_example_directed_graph():
"""Use GraphViz `dot` to layout a directed multigraph.
Creates a file named 'example_directed_graph' that contains
the rendered graph.
"""
g = example_directed_graph()
h = networkx_to_graphviz(g)
filename = 'example_directed_graph'
fileformat = 'pdf'
h.render(filename, format=fileformat, cleanup=True)
# The argument `view=True` can be given to
# the method `graphviz.dot.Digraph.render`
# to open the rendered file with the
# default viewer of the operating system
def dump_example_undirected_graph():
"""Use GraphViz `dot` to layout an undirected multigraph.
Creates a file named `example_undirected_graph` that contains
the rendered graph.
"""
g = example_undirected_graph()
h = networkx_to_graphviz(g)
filename = 'example_undirected_graph'
fileformat = 'pdf'
h.render(filename, format=fileformat, cleanup=True)
def example_directed_graph():
"""Return a sample directed graph as `networkx.MultiDiGraph`."""
g = nx.MultiDiGraph()
g.add_node(1, label='A')
g.add_node(2, label='B')
g.add_edge(1, 2, label='AB-1')
g.add_edge(1, 2, label='AB-2')
g.add_edge(2, 1, label='BA')
return g
def example_undirected_graph():
"""Return a sample undirected graph as `networkx.MultiGraph`."""
g = nx.MultiGraph()
g.add_node(1, label='A')
g.add_node(2, label='B')
g.add_edge(1, 2, label='AB-1')
g.add_edge(1, 2, label='AB-2')
return g
def networkx_to_graphviz(g):
"""Convert `networkx` graph `g` to `graphviz.Digraph`.
@type g: `networkx.Graph` or `networkx.DiGraph`
@rtype: `graphviz.Digraph`
"""
if g.is_directed():
h = gv.Digraph()
else:
h = gv.Graph()
for u, d in g.nodes(data=True):
h.node(str(u), label=d['label'])
for u, v, d in g.edges(data=True):
h.edge(str(u), str(v), label=d['label'])
return h
if __name__ == '__main__':
dump_example_directed_graph()
dump_example_undirected_graph()
Documentation of the:文档:
graphviz.dot.Graph
for representing undirected graphs用于表示无向图的类graphviz.dot.Graph
graphviz.dot.Digraph
for representing directed graphs 类graphviz.dot.Digraph
用于表示有向图graphviz.dot.Digraph.node
for adding an annotated node to a graph 方法graphviz.dot.Digraph.node
用于将带注释的节点添加到图形graphviz.dot.Digraph.edge
for adding an annotated edge to a graph 方法graphviz.dot.Digraph.edge
用于向图形添加带注释的边networkx.MultiGraph
for representing undirected graphs用于表示无向图的networkx.MultiGraph
类networkx.MultiDiGraph
for representing directed graphs用于表示有向图的networkx.MultiDiGraph
类The above code uses networkx == 2.5.1
, graphviz == 0.16
, and GraphViz version 2.40.1.上面的代码使用networkx == 2.5.1
、 graphviz == 0.16
和 GraphViz 版本 2.40.1。
matplotlib
使用matplotlib
当前可能性It appears that currently networkx
supports:看来目前networkx
支持:
networkx.drawing.nx_pylab.draw_networkx_edges
with the argument connectionstyle
, or使用函数networkx.drawing.nx_pylab.draw_networkx_edges
和参数connectionstyle
未标记的曲线边缘,或networkx.drawing.nx_pylab.draw_networkx_edges
with the argument edge_labels
.使用函数networkx.drawing.nx_pylab.draw_networkx_edges
和参数edge_labels
标记直边。 So as of networkx <= 2.5.1
, labeled curved edges cannot be drawn with matplotlib
.因此,从networkx <= 2.5.1
,无法使用matplotlib
绘制标记的曲线边缘。 As a result, for a directed graph with a pair of labeled edges that connect the same nodes (eg, an edge 1 -> 2
and an edge 2 -> 1
), the edges would be drawn in matplotlib
to overlap, so not all edge labels will be visible.因此,对于具有连接相同节点的一对标记边(例如,边1 -> 2
和边2 -> 1
)的有向图,边将在matplotlib
绘制以重叠,因此并非所有边缘标签将可见。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.