在Networkx图形中跟随其边缘的图形标签 [英] Drawing labels that follow their edges in a Networkx graph
问题描述
使用Networkx,我需要以不同的方式显示多个边缘.为此,我使用了连接样式,有些边是直线,有些是 Arc3.问题是每条边都有一个标签,而标签不跟随这些样式中的边.
Working with Networkx, I have several edges that need to be displayed in different ways. For that I use the connectionstyle, some edges are straight lines, some others are 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 ?
谢谢
推荐答案
是的,可以使用 GraphViz 绘制 networkx
有向图的标记边.使用 Python 包 graphviz
的示例,Python 包 networkx
,而GraphViz 程序 dot
:
Yes, it is possible to draw labeled edges of networkx
directed graphs, by using GraphViz. An example using the Python package graphviz
, the Python package networkx
, and the GraphViz program 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()
文档:
- 类
graphviz.dot.Graph
表示无向图 - 类
graphviz.dot.Digraph
表示有向图 - 方法
graphviz.dot.Digraph.node
用于将带注释的节点添加到图 - 方法
graphviz.dot.Digraph.edge
用于向图中添加带注释的边 - class
networkx.MultiGraph
用于表示无向图 - class
networkx.MultiDiGraph
用于表示有向图
以上代码使用networkx == 2.5.1
、graphviz == 0.16
和GraphViz 2.40.1版本.
The above code uses networkx == 2.5.1
, graphviz == 0.16
, and GraphViz version 2.40.1.
似乎当前 networkx
支持:
- 使用函数
带有参数
connectionstyle
或 的networkx.drawing.nx_pylab.draw_networkx_edges - 使用函数
标记直边networkx.drawing.nx_pylab.draw_networkx_edges
带有参数edge_labels
.
因此,从 networkx< = 2.5.1
开始,不能使用 matplotlib
绘制带标签的弯曲边缘.因此,对于具有连接相同节点的一对标记边的有向图(例如,边 1 -> 2
和边 2 -> 1
>),边缘将在 matplotlib
中绘制以重叠,因此并非所有边缘标签都可见.
So as of networkx <= 2.5.1
, labeled curved edges cannot be drawn with matplotlib
. As a result, for a directed graph with a pair of labeled edges that connect the same nodes (e.g., 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.
这篇关于在Networkx图形中跟随其边缘的图形标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!