Pertanyaan Menentukan node secara terprogram dari peringkat yang sama dalam wrapper networkx untuk pygraphviz / dot


Apakah mungkin untuk mengubah kode berikut untuk menempatkan Child_4 pada tingkat horizontal yang sama dengan Grandchild_0 (dengan demikian mendorong Grandchild_4 ke levelnya sendiri)?

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_edge("ROOT", "Child_%i" % i)
    G.add_edge("Child_%i" % i, "Grandchild_%i" % i)

pos=nx.graphviz_layout(G,prog='dot')
nx.draw(G,pos,arrows=False)
plt.show()

Kode di atas menghasilkan tata letak berikut, yang ingin saya ubah dengan menggeser anak ke satu tingkat agar sejajar secara horizontal dengan cucu: img shows a root node, five children, and a single grandchild beneath each child


Dalam jaringan networkx perpustakaan Python, saya menggunakan dot engine graphviz untuk membuat pohon (berikut rekomendasi ini). Saya ingin mengontrol y-posisi node dengan menentukan node mana yang memiliki ketinggian yang sama. Simpul mungkin berada pada kedalaman yang berbeda di pohon.

Saya tahu saya bisa mengendalikan ketinggian node jika saya menulis kode graphviz saya sendiri melalui menggunakan rank=same perintah (misalnya, {rank=same; n4 -> p2;} [ex.]). Namun, saya mengandalkan networkx.graphviz_layout () [dokter | sumber] untuk menghasilkan posisi simpul, dan graphviz_layout dapat mengirim hanya argumen baris perintah ke pygraphviz. Upaya saya untuk menggunakan varian nx.graphviz_layout(G, prog='dot', args="-Grank=same; n4 -> p2;") telah gagal. Apakah mungkin untuk menggambarkan ketinggian node yang diinginkan dalam bungkus NetworkX untuk pygraphviz, atau apakah saya perlu menulis wrapper saya sendiri di sekitar pygraphviz?  Edit: Jawabannya memberikan pembungkus baru di sekitar pygraphviz. Ini secara signifikan akan menyederhanakan hal-hal untuk mengirim informasi peringkat dalam pembungkus NetworkX yang ada untuk pygraphviz. Saya akan mengubah jawaban yang saya terima jika seseorang dapat memberi tahu saya bagaimana itu mungkin terjadi.


5
2018-03-12 04:02


asal


Jawaban:


Saya tidak dapat menemukan cara untuk mencapai hal ini melalui pembungkus jaringanx asli.

Sebaliknya, saya telah menulis pembungkus baru untuk pygraphviz, dengan sebagian besar baris disalin dari kode sumber. Ia menambahkan parameter sameRank = [] untuk daftar daftar nodes-of-the-same-rank dan a for mengitari sebuah doa pygraphviz.add_subgraph(listOfNodes,rank="same").

def graphviz_layout_with_rank(G, prog = "neato", root = None, sameRank = [], args = ""):
    ## See original import of pygraphviz in try-except block
    ## See original identification of root through command line
    A = nx.to_agraph(G)
    for sameNodeHeight in sameRank:
        if type(sameNodeHeight) == str:
            print("node \"%s\" has no peers in its rank group" %sameNodeHeight)
        A.add_subgraph(sameNodeHeight, rank="same")
    A.layout(prog=prog, args=args)
    ## See original saving of each node location to node_pos 
    return node_pos

Dalam contoh pertanyaan, Child_4 dapat didorong ke tingkat horizontal yang sama seperti Grandchild_0 melalui baris:

pos=graphviz_layout_with_rank(G, prog='dot',sameRank=[["Child_4","Grandchild_0"]])

3
2018-03-15 04:15