Czy istnieje sposób na zagwarantowanie hierarchicznego wyjścia z NetworkX?

86

Próbuję stworzyć schemat blokowy struktury drzewa . Udało mi się stworzyć reprezentatywne wykresy za pomocą networkx, ale potrzebuję sposobu, aby pokazać strukturę drzewa , kiedy wyprowadzam wykres. Do wykreślenia wykresu używam matplotlib.pylab.

Muszę pokazać dane w strukturze podobnej do pokazanej tutaj . Chociaż nie mam pod-grafów.

Jak mogę zagwarantować taką strukturę?

Przykłady dla niewierzących:

Różne układy NetworkX

Mogłem pokazać wykresy za pomocą pylab i graphviz, ale żadne z nich nie oferuje struktury drzewa, której szukam. Wypróbowałem każdy układ, jaki ma do zaoferowania networkx, ale żaden z nich nie pokazuje hierarchii . Po prostu nie jestem pewien, jakie opcje / tryb podać, LUB czy muszę użyć odważników. Wszelkie sugestie pomogłyby wielu.

@ jterrace:

Oto ogólny zarys tego, czego użyłem do stworzenia powyższych wykresów. Dodałem kilka etykiet, ale poza tym jest to to samo.

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
źródło

Odpowiedzi:

118

Jeśli używasz wykresu skierowanego, układ kropek Graphviz zrobi coś, co chcesz z drzewem. Oto kod podobny do powyższych rozwiązań, który pokazuje, jak to zrobić

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')

Wyjście Graphviz

Wyjście NetworkX / Matplotlib

AKTUALIZACJA

Oto wersja zaktualizowana dla networkx-2.0 (wraz z nadchodzącym networkx-2.1 rysuje również strzałki).

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')

wprowadź opis obrazu tutaj

Aric
źródło
1
Aha! Potrzebowałem więc tylko skierowanego wykresu z układem „kropek”. Wiedziałem, że to coś bardzo małego. Wielkie dzięki Aric!
maks.
Czy jest jakiś dobry sposób na oznaczanie węzłów rosnąco? Rozumiem przez to, że tworzę wykres g = nx.full_rary_tree(2, 10)Jeśli wydrukuję krawędzie, które otrzymam: [(0, 1), (0, 2), (1, 3), (1, 4), (2, 5), ... ]ale zwizualizuję je w innej kolejności ...
CodeKingPlusPlus
1
PyGrapviz działa z Pythonem 3, a ten kod będzie działał z Pythonem 3.
Aric
3
również jeśli napotkasz jakiś problem z instalacją pygraphvizw regularny sposób, spróbujpip install --install-option="--include-path=/usr/local/include/" --install-option="--library-path=/usr/local/lib/" pygraphviz
Rotail
2
@Rotail To zadziałało dla mnie po zainstalowaniu graphviz(w moim przypadku przy użyciu brew install graphviz).
Shivendra
10

Możesz użyć pygraphviz, aby się zbliżyć:

>>> 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')

Wynik: wprowadź opis obrazu tutaj

Uwaga Skopiowałem opcje graphviz z linku, który zamieściłeś powyżej. Nie jestem pewien, dlaczego czwarte dziecko jest rysowane na górze, a nie w ściśle pionowym formacie. Może ktoś, kto wie więcej o opcjach Graphviz, może w tym pomóc.

jterrace
źródło
dzięki. To było dokładnie to, co widziałem, kiedy tego próbowałem. Wydaje mi się nieco dziwne, dlaczego stworzył coś takiego.
maksymalnie
5
Zauważ, że w wersji 1.11 networkx zmienił się interfejs API. to_agraphFunkcja znajduje się teraz nx.nx_agraph.to_agraph.
m00 rano
1
Czy istnieje sposób, aby upewnić się, że dziecko jest zawsze poniżej swoich rodziców?
Dror