Is there a way to guarantee hierarchical output from NetworkX?

前端 未结 3 1357
不知归路
不知归路 2020-11-28 01:56

I\'m trying to produce a flow diagram of a tree structure. I\'ve been able to create representative graphs with networkx, but I need a way to show the

相关标签:
3条回答
  • 2020-11-28 02:10

    You can use pygraphviz to get close:

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

    Result: enter image description here

    Note I copied the graphviz options from the link you posted above. I'm not sure why the 4th child is drawn on top instead of in strictly vertical format. Maybe someone who knows more about the Graphviz options can help with that.

    0 讨论(0)
  • 2020-11-28 02:25

    If you use a directed graph then the Graphviz dot layout will do something like you want with the tree. Here is some code similar to the above solutions that shows how to do that

    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 output

    NetworkX/Matplotlib output

    UPDATED

    Here is a version updated for networkx-2.0 (and with upcoming networkx-2.1 draws arrows too).

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

    0 讨论(0)
  • 2020-11-28 02:31

    You can use grandalf for a python-only solution, if you don't want to install graphviz.

    Also, this type of visualization is called a layered graph drawing or Sugiyama-style graph drawing, which can display many kinds of graphs, including non-trees.

    See my answer to a different question for details and implementation.

    0 讨论(0)
提交回复
热议问题