Gibt es eine Möglichkeit, die hierarchische Ausgabe von NetworkX zu gewährleisten?

85

Ich versuche ein Flussdiagramm einer Baumstruktur zu erstellen . Ich konnte mit networkx repräsentative Diagramme erstellen, aber ich brauche eine Möglichkeit, die Baumstruktur bei der Ausgabe eines Diagramms anzuzeigen . Ich verwende matplotlib.pylab, um das Diagramm zu zeichnen.

Ich muss die Daten in einer Struktur anzeigen, die der hier gezeigten ähnlich ist . Obwohl ich keine Subgraphen habe.

Wie kann ich eine solche Struktur garantieren?

Beispiele für die Ungläubigen:

Verschiedene NetworkX-Layouts

Ich konnte die Grafiken mit Pylab und Graphviz anzeigen, biete aber auch nicht die Baumstruktur an, nach der ich suche. Ich habe jedes Layout ausprobiert, das networkx zu bieten hat, aber keines von ihnen weist eine Hierarchie auf . Ich bin mir nur nicht sicher, welche Optionen / Modi ich geben soll ODER ob ich Gewichte verwenden muss. Irgendwelche Vorschläge würden einem Haufen helfen.

@jterrace:

Hier ist ein grober Überblick darüber, was ich zur Erstellung der obigen Diagramme verwendet habe. Ich habe einige Labels hinzugefügt, aber ansonsten ist es dasselbe.

import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()

G.add_node("ROOT")

for i in xrange(5):
    G.add_node("Child_%i" % i)
    G.add_node("Grandchild_%i" % i)
    G.add_node("Greatgrandchild_%i" % i)

    G.add_edge("ROOT", "Child_%i" % i)
    G.add_edge("Child_%i" % i, "Grandchild_%i" % i)
    G.add_edge("Grandchild_%i" % i, "Greatgrandchild_%i" % i)

plt.title("draw_networkx")
nx.draw_networkx(G)

plt.show()
max
quelle

Antworten:

117

Wenn Sie ein gerichtetes Diagramm verwenden, führt das Graphviz-Punktlayout mit dem Baum so aus, wie Sie es möchten. Hier ist ein Code ähnlich den obigen Lösungen, der zeigt, wie das geht

import networkx as nx
from networkx.drawing.nx_agraph import graphviz_layout
import matplotlib.pyplot as plt
G = nx.DiGraph()

G.add_node("ROOT")

for i in range(5):
    G.add_node("Child_%i" % i)
    G.add_node("Grandchild_%i" % i)
    G.add_node("Greatgrandchild_%i" % i)

    G.add_edge("ROOT", "Child_%i" % i)
    G.add_edge("Child_%i" % i, "Grandchild_%i" % i)
    G.add_edge("Grandchild_%i" % i, "Greatgrandchild_%i" % i)

# write dot file to use with graphviz
# run "dot -Tpng test.dot >test.png"
nx.nx_agraph.write_dot(G,'test.dot')

# same layout using matplotlib with no labels
plt.title('draw_networkx')
pos=graphviz_layout(G, prog='dot')
nx.draw(G, pos, with_labels=False, arrows=False)
plt.savefig('nx_test.png')

Graphviz-Ausgabe

NetworkX / Matplotlib-Ausgabe

AKTUALISIERT

Hier ist eine Version, die für networkx-2.0 aktualisiert wurde (und mit dem kommenden networkx-2.1 auch Pfeile zeichnet).

import networkx as nx
from networkx.drawing.nx_agraph import write_dot, graphviz_layout
import matplotlib.pyplot as plt
G = nx.DiGraph()

G.add_node("ROOT")

for i in range(5):
    G.add_node("Child_%i" % i)
    G.add_node("Grandchild_%i" % i)
    G.add_node("Greatgrandchild_%i" % i)

    G.add_edge("ROOT", "Child_%i" % i)
    G.add_edge("Child_%i" % i, "Grandchild_%i" % i)
    G.add_edge("Grandchild_%i" % i, "Greatgrandchild_%i" % i)

# write dot file to use with graphviz
# run "dot -Tpng test.dot >test.png"
write_dot(G,'test.dot')

# same layout using matplotlib with no labels
plt.title('draw_networkx')
pos =graphviz_layout(G, prog='dot')
nx.draw(G, pos, with_labels=False, arrows=True)
plt.savefig('nx_test.png')

Geben Sie hier die Bildbeschreibung ein

Aric
quelle
1
Ah ha! Alles was ich brauchte war ein gerichteter Graph mit dem 'Punkt'-Layout. Ich wusste, dass es etwas sehr Kleines war. Vielen Dank Aric!
Max
Gibt es eine gute Möglichkeit, die Knoten aufsteigend zu kennzeichnen? Damit meine ich, ich erstelle ein Diagramm. g = nx.full_rary_tree(2, 10)Wenn ich die Kanten [(0, 1), (0, 2), (1, 3), (1, 4), (2, 5), ... ]
drucke,
1
PyGrapviz funktioniert mit Python 3 und dieser Code funktioniert mit Python 3.
Aric
3
Auch wenn Sie Probleme pygraphvizbei der regelmäßigen Installation haben , versuchen Sie espip install --install-option="--include-path=/usr/local/include/" --install-option="--library-path=/usr/local/lib/" pygraphviz
Rotail
2
@ Rotail Dies funktionierte für mich nach der Installation graphviz(in meinem Fall mit brew install graphviz).
Shivendra
10

Sie können pygraphviz verwenden, um näher zu kommen:

>>> import pygraphviz
>>> import networkx
>>> import networkx as nx
>>> G = nx.Graph()
>>> G.add_node("ROOT")
>>> for i in xrange(5):
...     G.add_node("Child_%i" % i)
...     G.add_node("Grandchild_%i" % i)
...     G.add_node("Greatgrandchild_%i" % i)
...     G.add_edge("ROOT", "Child_%i" % i)
...     G.add_edge("Child_%i" % i, "Grandchild_%i" % i)
...     G.add_edge("Grandchild_%i" % i, "Greatgrandchild_%i" % i)

>>> A = nx.to_agraph(G)
>>> A.layout('dot', args='-Nfontsize=10 -Nwidth=".2" -Nheight=".2" -Nmargin=0 -Gfontsize=8')
>>> A.draw('test.png')

Ergebnis: Geben Sie hier die Bildbeschreibung ein

Hinweis: Ich habe die graphviz-Optionen von dem oben angegebenen Link kopiert. Ich bin mir nicht sicher, warum das 4. Kind nicht streng vertikal, sondern oben gezeichnet wird. Vielleicht kann jemand helfen, der mehr über die Graphviz-Optionen weiß.

jterrace
quelle
Vielen Dank. Genau das habe ich gesehen, als ich es ausprobiert habe. Ich finde es etwas seltsam, warum es so etwas hervorgebracht hat.
Max
5
Beachten Sie, dass sich die API in Version 1.11 von networkx geändert hat. Die to_agraphFunktion befindet sich jetzt in nx.nx_agraph.to_agraph.
m00am
1
Gibt es eine Möglichkeit, um sicherzustellen, dass das Kind immer unter seinen Eltern ist?
Dror