Plotting directed graphs in Python in a way that show all edges separately

networkx graph visualization
graphviz
python plot graph nodes, edges
directed graph python
networkx print graph
graphviz python
matplotlib directed graph
plot edges python

I'm using Python to simulate a process that takes place on directed graphs. I would like to produce an animation of this process.

The problem that I've run into is that most Python graph visualization libraries combine pairs of directed edges into a single edge. For example, NetworkX draws only two edges when displaying the following graph, whereas I would like to display each of the four edges separately:

import networkx as nx
import matplotlib.pyplot as plt 

G = nx.MultiDiGraph()

G.add_edges_from([
    (1, 2),
    (2, 3),
    (3, 2),
    (2, 1),
])

plt.figure(figsize=(8,8))
nx.draw(G)

I would like to display something like this, with each parallel edge drawn separately:

The question R reciprocal edges in igraph in R seems to deal with the same issue, but the solution there is for the R igraph library, not the Python one.

Is there an easy way to produce this style of plot using an existing Python graph visualization library? It would be a bonus if it could support multigraphs.

I'm open to solutions that invoke an external program to produce the images. I'd like to generate a whole series of animation frames, so the solution must be automated.

The Graphviz tools appear to display distinct edges.

For example, giving this:

digraph G {
  A -> B;
  A -> B;
  A -> B;
  B -> C;

  B -> A;
  C -> B;
}

to dot produces:

Graphviz's input language is pretty simple so you can generate it on your own, though searching for "python graphviz" does turn up a couple of libraries including a graphviz module on PyPI.

Here's python that generates the above graph using the graphviz module:

from graphviz import Digraph

dot = Digraph()
dot.node('A', 'A')
dot.node('B', 'B')
dot.node('C', 'C')
dot.edges(['AB', 'AB', 'AB', 'BC', 'BA', 'CB'])

print(dot.source)
dot.render(file_name, view=True)

Directed Graphs, Multigraphs and Visualization in Networkx , Plotting directed graphs in Python in a way that show all edges separately. I'm using Python to simulate a process that takes place on directed graphs. I would� Display graph edges. Finding the graph edges is little tricker than the vertices as we have to find each of the pairs of vertices which have an edge in between them. So we create an empty list of edges then iterate thorugh the edge values associated with each of the vertices.

Using NetworkX, a possible workaround which avoids file I/O and uses dot via pydot for layout is:

import networkx as nx
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from io import BytesIO

g = nx.dodecahedral_graph()
d = nx.drawing.nx_pydot.to_pydot(g) # d is a pydot graph object, dot options can be easily set
# attributes get converted from networkx,
# use set methods to control dot attributes after creation

png_str = d.create_png()
sio = BytesIO() # file-like string, appropriate for imread below
sio.write(png_str)
sio.seek(0)

img = mpimg.imread(sio)
imgplot = plt.imshow(img)

for why seek(0) is needed, see How to create an image from a string in python

If within IPython (qt)console, then the above will print inline and a more direct approach is:

import networkx as nx
from IPython.display import Image

g = nx.dodecahedral_graph()
d = nx.drawing.nx_pydot.to_pydot(g)

png_str = d.create_png()
Image(data=png_str)

Tutorial — NetworkX 2.4 documentation, Directed Graphs, Multigraphs and Visualization in Networkx Add list of all edges along with assorted weights – a Path Graph, i.e. a straight line connecting a number of nodes in the following manner: It fails to show multiple edges separately and these edges overlap. PUT method - Python requests. """Draw the edges of the graph G: This draws only the edges of the graph G. Parameters-----G : graph: A networkx graph : pos : dictionary: A dictionary with nodes as keys and positions as values. If not specified a spring layout positioning will be computed. See networkx.layout for functions that compute node positions.

Maybe I am a little late but I found another solution to you issue, so I post it so that can be helpful if somebody has the same problem. This is adding the connectionstyle argument to nx.draw:

import networkx as nx
import matplotlib.pyplot as plt 

G = nx.MultiDiGraph()

G.add_edges_from([
    (1, 2),
    (2, 3),
    (3, 2),
    (2, 1),
])

plt.figure(figsize=(8,8))
nx.draw(G, connectionstyle='arc3, rad = 0.1',)

Here you see the result:

MultiDiGraph, Create an empty graph with no nodes and no edges. Python's None object should not be used as a node as it determines whether G and have a separate dictionary keyed by identifier to the node information if you prefer. by adding a list of edges, For example, after removing all nodes and edges,. I have 2300 edges with rare connection. This is my plot of it: And here are zooms of a few parts of it: This plot is not readable because the distance between edges is too small. How can I have a bigger distance between edges? Only edges from the same 'family' have small distance. Is there any other way to improve plots with a lot of edges? I'm

You can do it by using the matplotlib interface:

G=nx.MultiGraph ([(1, 2),
   (2, 3),
   (3, 2),
   (2, 1)])
pos = {1: (0.4,0.5), 2: (0.5,0.5), 3: (0.6,0.5)}
nx.draw_networkx_nodes(G, pos, node_color = 'k', node_size = 100, alpha = 1)
ax = plt.gca()
for e in G.edges:
    ax.annotate("",
                xy=pos[e[0]], xycoords='data',
                xytext=pos[e[1]], textcoords='data',
                arrowprops=dict(arrowstyle="->", color="0.5",
                                shrinkA=5, shrinkB=5,
                                patchA=None, patchB=None,
                                connectionstyle="arc3,rad=rrr".replace('rrr',str(2*(e[2]-0.5))
                                ),
                                ),
                )
plt.axis('off')
plt.show()

graphs, Nodes can be arbitrary (hashable) Python objects with optional key/value attributes. The data can be an edge list, or any NetworkX graph object. The fastest way to traverse all edges of a graph is via adjacency_iter(), but the edges ()� Finally, we plot the points by passing x and y arrays to the plt.plot() function. So, in this part, we discussed various types of plots we can create in matplotlib. There are more plots which haven’t been covered but the most significant ones are discussed here – Graph Plotting in Python | Set 2; Graph Plotting in Python | Set 3

Network Graphs — HoloViews 1.13.2 documentation, Graphs typically come in two flavors: undirected and directed, each having their as a directed graph where the tasks are the nodes and the directed edges encode Since the plotting is being done by matplotlib you can do this, for example, as follows: K33 = nx.complete_bipartite_graph(3,3) nx.draw(K33) plt. show(). Plotting happens separately on the matplotlib or Bokeh backends, so you can focus on the data, not writing plotting code. The main interactive function HoloViews offers are sliders so folks can play with a variable to see its effect.

Visualizing Network Graphs — Bokeh 2.1.1 Documentation, The Graph itself holds the abstract edges stored as a table of node indices. Let's start by declaring a very simple graph connecting one node to all others. By setting directed=True as a plot option it is possible to indicate the directionality number of edges we can datashade the paths and display the nodes separately. Well I know its probably not what you're looking for, but I was facing a similar problem where I wanted to have a directed graph where the edge between two nodes had a different weight depending on the direction (whether it was going into or out of the node) and the work around I did was I used a different color for each edge and decreased the opacity for one of them so it would show even if

Graphs, The ColumnDataSource associated with the edge sub-renderer has two import math from bokeh.plotting import figure from bokeh.models import list(range(N)) plot = figure(title="Graph Layout Demonstration", x_range=(-1.1 Bokeh uses a separate LayoutProvider model in order to supply the coordinates of a graph in� History of Graph Theory Graph Theory started with the "Seven Bridges of Königsberg". The city of Königsberg (formerly part of Prussia now called Kaliningrad in Russia) spread on both sides of the Pregel River, and included two large islands which were connected to each other and the mainland by seven bridges.

Comments
  • Related stackoverflow.com/questions/15053686/…
  • It turns out that NetworkX can export .dot files using pydot or pygraphviz, so this works perfectly. Thanks!
  • Both links are dead @JoshRosen
  • I am having following error: Format: "pdf" not recognized. Use one of@Laurence Gonsalves
  • @alper I believe it's possible to select the output formats at build time. You may need to install a different distribution of graphviz, or build your own.
  • This example needs to be updated: nx.to_pydot is no longer available. Instead you should pip install pydotplus and then use nx.drawing.nx_pydot.to_pydot instead.
  • Thanks for raising the need to update this example, I updated it. pydotplus has already been reverted to pydot in upstream networkx, please see this PR.
  • If pydotplus does not find your graphviz instalation it will throw InvocationException: GraphViz's executables not found. A workaround is to add it to system path for current execution like this: import os then os.environ["PATH"] += r";C:\Anaconda\envs\testes\Library\bin\graphviz" where you should replace the folder where your graphviz executables are located.
  • pydotplus is an unmaintained fork of pydot. pydot == 1.2.3 will look for GraphViz executables only in the $PATH, for the reasons described in this issue and issues referenced in it. Adding the relevant paths to the environment's $PATH variable isn't a workaround, but the proper way of declaring where GraphViz is located. Please consider using .bashrc or an equivalent, instead of modifying os.environ at runtime.