Robin Andrews
Robin Andrews

Reputation: 3794

Networkx Two Edges Instead of One to Show a Loop

In the graph produced by the code below, B->D and D->B

I would like this "loop" to be represented by two lines (one would probably need to be curved), rather than a single line with arrows at both ends. How do I achieve this please?

enter image description here

import networkx as nx
import matplotlib.pyplot as plt

G = nx.DiGraph()
G.add_edges_from(
    [('A', 'B'), ('A', 'C'), ('D', 'B'), ('E', 'C'), ('E', 'F'),
     ('B', 'H'), ('B', 'G'), ('B', 'D'), ('C', 'G')])

pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos, node_size = 500)
nx.draw_networkx_labels(G, pos)
nx.draw_networkx_edges(G, pos, arrows=True)
plt.show()

Upvotes: 2

Views: 309

Answers (3)

mathfux
mathfux

Reputation: 5949

If you don't mind using alternative libraries igraph is able to do it automatically:

import igraph as ig
g = ig.Graph(directed=True)
nodes = list('ABCDEFGH')
edges = [('A', 'B'), ('A', 'C'), ('D', 'B'), ('E', 'C'), ('E', 'F'),
     ('B', 'H'), ('B', 'G'), ('B', 'D'), ('C', 'G')]

g.add_vertices(g_nodes)
g.add_edges(g_edges)

ig.plot(g,  
        bbox = (400, 200), # bounding box of plot
        vertex_color='lightblue',
        vertex_label=nodes,
        vertex_frame_width=3)

enter image description here

But there are some differences that might be important:

  • Only consecutive integers starting from 0 can be used as vertex indices, so you need to add a mapping manually:

     idx = dict(zip(nodes, range(len(nodes))))
     g_nodes = [idx[A] for A in nodes]
     g_edges = [(idx[A], idx[B]) for A, B in edges]
    
  • It uses internal surface that is quite limitted instead of matplotlib. Note that you need define size of diagram yourself.

  • It requires to have igraph and pycairo installed

Upvotes: 1

Gambit1614
Gambit1614

Reputation: 8801

You can do it directly by specifying the connection style in nx.draw_edges, although the edges won't be in a straight line:

import networkx as nx
import matplotlib.pyplot as plt

plt.figure(1,figsize=(12,12)) 

G = nx.MultiDiGraph()
G.add_edges_from(
    [('A', 'B'), ('A', 'C'), ('D', 'B'), ('E', 'C'), ('E', 'F'),
     ('B', 'H'), ('B', 'G'), ('B', 'D'), ('C', 'G')])

pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos, node_size = 500)
nx.draw_networkx_labels(G, pos)
nx.draw_networkx_edges(G, pos, connectionstyle='arc3, rad = 0.1', width = 2, arrows=True)
plt.show()

enter image description here

References:

Upvotes: 1

abc
abc

Reputation: 11929

You could use PyGraphviz

>>> A = nx.nx_agraph.to_agraph(G)
>>> A.draw("G.ps",prog='circo')

Upvotes: 2

Related Questions