使用Networkx时,我需要以不同的方式显示多个边缘。 为此,我使用connectionstyle,一些边缘为直线,另一些为Arc3。 问题在于每个边缘都有一个标签,并且标签不遵循这些样式中的边缘。
我借了一个图作为示例:
#!/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()
这可能导致出现如下所示的问题 this example image:我们不确定标签的边缘是什么。
有没有办法画沿其边缘的标签?
谢谢
答案 0 :(得分:1)
是的,可以使用 GraphViz 绘制 networkx
有向图的标记边。使用 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()
文档:
graphviz.dot.Graph
表示无向图graphviz.dot.Digraph
表示有向图graphviz.dot.Digraph.node
用于向图中添加带注释的节点graphviz.dot.Digraph.edge
用于向图形添加带注释的边networkx.MultiGraph
表示无向图networkx.MultiDiGraph
表示有向图以上代码使用 networkx == 2.5.1
、graphviz == 0.16
和 GraphViz 版本 2.40.1。
matplotlib
的当前可能性目前看来 networkx
支持:
networkx.drawing.nx_pylab.draw_networkx_edges
和参数 connectionstyle
未标记的曲线边缘,或networkx.drawing.nx_pylab.draw_networkx_edges
和参数 edge_labels
标记直边。所以从 networkx <= 2.5.1
开始,标记的曲线边缘不能用 matplotlib
绘制。因此,对于具有连接相同节点的一对标记边(例如,边 1 -> 2
和边 2 -> 1
)的有向图,边将绘制在 matplotlib
重叠,因此并非所有边缘标签都可见。