简体   繁体   English

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

[英]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 包networkxGraphViz程序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:文档:

The above code uses networkx == 2.5.1 , graphviz == 0.16 , and GraphViz version 2.40.1.上面的代码使用networkx == 2.5.1graphviz == 0.16和 GraphViz 版本 2.40.1。

Current possibilities using matplotlib使用matplotlib当前可能性

It appears that currently networkx supports:看来目前networkx支持:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM