Python >> Tutoriel Python >  >> Python

Tracer des graphiques orientés en Python de manière à afficher toutes les arêtes séparément

Les outils Graphviz semblent afficher des bords distincts.

Par exemple, donner ceci :

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

  B -> A;
  C -> B;
}

à dot produit :

Le langage d'entrée de Graphviz est assez simple, vous pouvez donc le générer vous-même, bien que la recherche de "python graphviz" fasse apparaître quelques bibliothèques, dont un graphviz module sur PyPI.

Voici python qui génère le graphique ci-dessus en utilisant le graphviz modules :

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)

En utilisant NetworkX, une solution de contournement possible qui évite les E/S de fichiers et utilise point via pydot pour la mise en page est :

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)

pourquoi seek(0) est nécessaire, voir Comment créer une image à partir d'une chaîne en python

Si dans la console IPython (qt), alors ce qui précède s'imprimera en ligne et une approche plus directe est :

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)

Je suis peut-être un peu en retard mais j'ai trouvé une autre solution à votre problème, donc je la poste pour que cela puisse être utile si quelqu'un a le même problème. Ceci ajoute l'argument connectionstyle à 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',)

Ici vous voyez le résultat :