Có cách nào để đảm bảo đầu ra phân cấp từ NetworkX không?


84

Tôi đang cố gắng tạo sơ đồ cấu trúc cây . Tôi đã có thể tạo đồ thị đại diện với networkx, nhưng tôi cần một cách để hiển thị cấu trúc cây khi tôi xuất một biểu đồ. Tôi đang sử dụng matplotlib.pylab để vẽ biểu đồ.

Tôi cần hiển thị dữ liệu theo cấu trúc tương tự như những gì được hiển thị ở đây . Mặc dù tôi không có đồ thị phụ.

Làm thế nào tôi có thể đảm bảo một cấu trúc như vậy?

Ví dụ cho những người không tin:

Các bố cục NetworkX khác nhau

Tôi đã có thể hiển thị các biểu đồ bằng pylab và graphviz, nhưng cả hai đều không đưa ra cấu trúc cây mà tôi đang tìm kiếm. Tôi đã thử mọi cách bố trí mà networkx cung cấp, nhưng không có cách nào trong số chúng hiển thị thứ bậc . Tôi chỉ không chắc chắn những tùy chọn / chế độ nào để cung cấp cho nó HOẶC nếu tôi cần sử dụng tạ. Bất kỳ đề xuất sẽ giúp một loạt.

@jterrace:

Đây là bản phác thảo sơ bộ về những gì tôi đã sử dụng để tạo ra các mảnh ở trên. Tôi đã thêm một số nhãn, nhưng ngoài ra thì nó giống nhau.

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

Câu trả lời:


116

Nếu bạn sử dụng đồ thị có hướng thì bố cục chấm Graphviz sẽ thực hiện điều gì đó như bạn muốn với cây. Đây là một số mã tương tự như các giải pháp ở trên cho thấy cách thực hiện điều đó

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

Đầu ra Graphviz

Đầu ra NetworkX / Matplotlib

ĐÃ CẬP NHẬT

Đây là phiên bản được cập nhật cho networkx-2.0 (và với networkx-2.1 sắp tới cũng sẽ vẽ các mũi tên).

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

nhập mô tả hình ảnh ở đây


1
À ha! Vì vậy, tất cả những gì tôi cần là một biểu đồ có hướng với bố cục 'chấm'. Tôi biết nó là một cái gì đó rất nhỏ. Cảm ơn rất nhiều Aric!
tối đa

Có cách nào tốt để gắn nhãn các nút tăng dần không? Bởi rằng tôi có nghĩa là, tôi có thể tạo một đồ thị g = nx.full_rary_tree(2, 10)Nếu tôi in các cạnh tôi nhận được: [(0, 1), (0, 2), (1, 3), (1, 4), (2, 5), ... ]nhưng nó sẽ hình dung chúng theo một thứ tự khác nhau ...
CodeKingPlusPlus

1
PyGrapviz làm việc với Python 3 và mã này sẽ làm việc với Python 3.
Aric

3
Ngoài ra, nếu bạn gặp phải bất kỳ sự cố nào khi cài đặt pygraphviztheo cách thông thường, hãy thửpip install --install-option="--include-path=/usr/local/include/" --install-option="--library-path=/usr/local/lib/" pygraphviz
Rotail 23/02

2
@Rotail Điều này đã làm việc cho tôi sau khi tôi cài đặt graphviz(trong trường hợp của tôi là sử dụng brew install graphviz).
Shivendra

10

Bạn có thể sử dụng pygraphviz để đến gần:

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

Kết quả: nhập mô tả hình ảnh ở đây

Lưu ý rằng tôi đã sao chép các tùy chọn graphviz từ liên kết bạn đã đăng ở trên. Tôi không chắc tại sao con thứ 4 lại được vẽ trên cùng thay vì ở định dạng thẳng đứng. Có thể ai đó biết thêm về các tùy chọn Graphviz có thể giúp bạn với điều đó.


cảm ơn. Đây chính xác là những gì tôi đã thấy khi tôi thử nó. Tôi thấy hơi lạ tại sao nó lại tạo ra thứ như thế này.
tối đa

5
Lưu ý rằng trong phiên bản 1.11 của networkx, api đã thay đổi. Các to_agraphchức năng hiện đang nằm trong nx.nx_agraph.to_agraph.
m00am

1
Có cách nào để đảm bảo rằng đứa trẻ đó luôn ở dưới cha mẹ chúng không?
Dror

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.