python - 在 Networkx 图中绘制跟随其边缘的标签

标签 python matplotlib networkx

使用 Networkx,我有几个需要以不同方式显示的边。
为此,我使用了连接样式,有些边是直线,有些是 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 :我们不确定哪个边缘是标签。

有没有办法绘制跟随其边缘的标签?

谢谢

最佳答案

是的,可以绘制 networkx 的标记边缘有向图,通过使用 GraphViz。使用 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()
文档:
  • class graphviz.dot.Graph 用于表示无向图
  • class graphviz.dot.Digraph 用于表示有向图
  • method graphviz.dot.Digraph.node 用于将带注释的节点添加到图形
  • method graphviz.dot.Digraph.edge 用于向图形添加带注释的边
  • class networkx.MultiGraph 用于表示无向图
  • class 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 中。重叠,因此并非所有边缘标签都可见。

    关于python - 在 Networkx 图中绘制跟随其边缘的标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60657926/

    相关文章:

    python - Eclipse + PyDev 在大量导入时变得极其缓慢

    python - 在 OSX 上使用 openMP 支持编译 cython

    python - 如何在 xaxis 末尾设置我的 xlabel

    python - 将组 ID 分配给 networkx 中的组件

    python - "MEIPASS"代表什么?

    python - Seaborn 的多个直方图

    python - 在 SymPy 中绘制 3D 点列表

    python - 为什么我无法使用 networkx 和请求获取某个网站 url 的 IP 地址?

    Python:将轨迹分成几步

    python - 如何读取大文件(套接字编程和python)?