2012-07-13 16 views
45

Estoy tratando de producir un diagrama de flujo de una estructura árbol. He podido crear gráficos representativos con networkx, pero necesito una forma de mostrar la estructura del árbol cuando genero un gráfico. Estoy usando matplotlib.pylab para trazar el gráfico.¿Hay alguna forma de garantizar una salida jerárquica desde NetworkX?

Necesito mostrar los datos en una estructura similar a la que se muestra here. Aunque no tengo sub-gráficos.

¿Cómo puedo garantizar una estructura como esa?

Ejemplos para los incrédulos:

Various NetworkX layouts

que he sido capaz de mostrar los gráficos con pylab y graphviz, pero no ofrecerán la estructura de árbol que estoy buscando. He intentado todos los diseños que networkx tiene para ofrecer, pero ninguno de ellos muestra una jerarquía . Simplemente no estoy seguro de qué opciones /modo para darle O si necesito usar pesos. Cualquier sugerencia ayudaría mucho.

@jterrace:

Aquí hay un esbozo de lo que he utilizado para producir las parcelas anteriormente. He agregado algunas etiquetas, pero aparte de eso, es lo mismo.

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

Respuesta

64

Si usa un gráfico dirigido, el diseño de puntos de Graphviz hará algo como lo que quiere con el árbol. Aquí hay un código similar a las soluciones anteriores que muestra cómo hacer que

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

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) 

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

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

Graphviz output

NetworkX/Matplotlib output

ACTUALIZADO

Aquí está una versión actualizada para NetworkX-2.0 (y con el próximo networkx-2.1 también dibuja flechas).

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

enter image description here

+0

¡Ah, ja! Así que todo lo que necesitaba era un gráfico dirigido con el diseño 'punto'. Sabía que era algo muy pequeño. Muchas gracias Aric! – max

+0

¿Hay alguna buena manera de etiquetar los nodos de forma ascendente? Con eso quiero decir, creo un gráfico 'g = nx.full_rary_tree (2, 10)' Si imprimo los bordes obtengo: '[(0, 1), (0, 2), (1, 3), (1, 4), (2, 5), ...] 'pero los visualizará en un orden diferente ... – CodeKingPlusPlus

+0

¿Qué orden desea? Ver bfs_edges() y dfs_edges(). – Aric

6

Puede utilizar pygraphviz de acercarse:

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

Resultado: enter image description here

Nota Copié las opciones graphviz desde el enlace que envió por encima. No estoy seguro de por qué el cuarto niño se dibuja en la parte superior en lugar de en formato estrictamente vertical. Quizás alguien que sepa más sobre las opciones de Graphviz puede ayudar con eso.

+0

gracias. Esto era exactamente lo que estaba viendo cuando lo probé. Me resulta un tanto extraño por qué produjo algo como esto. – max

+4

Tenga en cuenta que en la versión 1.11 de networkx cambió la API. La función 'to_agraph' ahora se encuentra en' nx.nx_agraph.to_agraph'. – m00am

Cuestiones relacionadas