làm thế nào để vẽ đồ thị có hướng bằng cách sử dụng networkx trong python?


101

Tôi có một số nút đến từ một tập lệnh mà tôi muốn ánh xạ vào biểu đồ. Trong phần bên dưới, tôi muốn sử dụng Mũi tên để đi từ A đến D và có thể có cạnh được tô màu (đỏ hoặc gì đó).

Về cơ bản, đây giống như một đường dẫn từ A đến D khi tất cả các nút khác đều có mặt. bạn có thể tưởng tượng mỗi nút là các thành phố và việc đi từ A đến D yêu cầu chỉ đường (có đầu mũi tên).

Đoạn mã này dưới đây xây dựng biểu đồ

import networkx as nx
import numpy as np
import matplotlib.pyplot as plt

G = nx.Graph()
G.add_edges_from(
    [('A', 'B'), ('A', 'C'), ('D', 'B'), ('E', 'C'), ('E', 'F'),
     ('B', 'H'), ('B', 'G'), ('B', 'F'), ('C', 'G')])

val_map = {'A': 1.0,
           'D': 0.5714285714285714,
           'H': 0.0}

values = [val_map.get(node, 0.25) for node in G.nodes()]

nx.draw(G, cmap = plt.get_cmap('jet'), node_color = values)
plt.show()

nhưng tôi muốn một cái gì đó như được hiển thị trong hình ảnh.nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Đầu mũi tên của hình ảnh đầu tiên và các cạnh màu đỏ trên hình ảnh thứ hai.

Câu trả lời:


86

Ví dụ hoàn toàn bổ sung với các mũi tên chỉ cho các cạnh màu đỏ:

import networkx as nx
import matplotlib.pyplot as plt

G = nx.DiGraph()
G.add_edges_from(
    [('A', 'B'), ('A', 'C'), ('D', 'B'), ('E', 'C'), ('E', 'F'),
     ('B', 'H'), ('B', 'G'), ('B', 'F'), ('C', 'G')])

val_map = {'A': 1.0,
           'D': 0.5714285714285714,
           'H': 0.0}

values = [val_map.get(node, 0.25) for node in G.nodes()]

# Specify the edges you want here
red_edges = [('A', 'C'), ('E', 'C')]
edge_colours = ['black' if not edge in red_edges else 'red'
                for edge in G.edges()]
black_edges = [edge for edge in G.edges() if edge not in red_edges]

# Need to create a layout when doing
# separate calls to draw nodes and edges
pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos, cmap=plt.get_cmap('jet'), 
                       node_color = values, node_size = 500)
nx.draw_networkx_labels(G, pos)
nx.draw_networkx_edges(G, pos, edgelist=red_edges, edge_color='r', arrows=True)
nx.draw_networkx_edges(G, pos, edgelist=black_edges, arrows=False)
plt.show()

Viền đỏ


1
Thật điên rồ khi hai hình ảnh cập nhật của chúng tôi khác nhau. +1 để tìm ra màu sắc cạnh!
mdml

tại sao cạnh của bạn (C, E) không có màu đỏ, mặc dù nó phải có màu đỏ theo mã của bạn ở trên?
cơn bão não

là không thể có những đầu mũi tên chỉ trên các cạnh quan tâm? ví dụ (A, C) và (C, E)
cơn bão não bộ

@ user1988876: À, xin lỗi, (C, E)không phải là màu đỏ vì tôi đã chọn các cạnh red_edgeskhi tôi vẫn đang làm việc với đồ thị vô hướng của bạn, chỉ chọn ngẫu nhiên từ các cạnh được trả về G.edges(). Nó nên được red_edges = [('A', 'C'), ('E', 'C')].
Marius

@ user1988876: Chỉ có thể có các mũi tên ở một số cạnh với các lệnh gọi riêng biệt tới draw_networkx_edges(). Tôi đã xóa mã và khắc phục sự cố DiGraph.
Marius

47

Tôi chỉ đưa cái này vào cho hoàn chỉnh. Tôi đã học được nhiều điều từ marius và mdml. Đây là trọng số các cạnh. Xin lỗi về các mũi tên. Có vẻ như tôi không phải là người duy nhất nói rằng điều đó không thể khác được. Tôi không thể hiển thị điều này với máy tính xách tay ipython, tôi phải truy cập thẳng từ python, đó là vấn đề với việc nhận trọng lượng cạnh của tôi sớm hơn.

import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
import pylab

G = nx.DiGraph()

G.add_edges_from([('A', 'B'),('C','D'),('G','D')], weight=1)
G.add_edges_from([('D','A'),('D','E'),('B','D'),('D','E')], weight=2)
G.add_edges_from([('B','C'),('E','F')], weight=3)
G.add_edges_from([('C','F')], weight=4)


val_map = {'A': 1.0,
                   'D': 0.5714285714285714,
                              'H': 0.0}

values = [val_map.get(node, 0.45) for node in G.nodes()]
edge_labels=dict([((u,v,),d['weight'])
                 for u,v,d in G.edges(data=True)])
red_edges = [('C','D'),('D','A')]
edge_colors = ['black' if not edge in red_edges else 'red' for edge in G.edges()]

pos=nx.spring_layout(G)
nx.draw_networkx_edge_labels(G,pos,edge_labels=edge_labels)
nx.draw(G,pos, node_color = values, node_size=1500,edge_color=edge_colors,edge_cmap=plt.cm.Reds)
pylab.show()

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


9
Tôi đã chạy điều này và không nhận được các nhãn nút. Bạn cần phải thêm sau đây: node_labels = {node:node for node in G.nodes()}; nx.draw_networkx_labels(G, pos, labels=node_labels).
MadeOfAir

Và điều gì sẽ xảy ra nếu bạn đã có một biểu đồ vô hướng và muốn tái tạo một bản sao có hướng của nó? Có cách nào để thiết lập G.add_edges_from()dòng mà không cần phải nhập điểm đầu và điểm cuối theo cách thủ công không? Có lẽ thêm các cạnh từ a dict?
FaCoffee

Dòng đầu tiên của mã trong phần này (không phải các dòng nhập) đặt loại biểu đồ và loại cạnh mà nó chấp nhận. Bạn có thể đi từ đồ thị (nhiều thông tin hơn) sang đồ thị (ít thông tin hơn) nhưng bạn không thể đi từ đồ thị (ít thông tin hơn) sang đồ thị (nhiều thông tin hơn) mà không có thông tin hoặc cách xây dựng thông tin bị thiếu đó. Tôi khuyên bạn nên đưa ra câu hỏi của bạn với một ví dụ trong một câu hỏi tràn ngăn xếp khác.
Back2Basics

1
Có thể nhận được các mũi tên thực trên các cạnh? Tôi không thích phần cuối dày hơn.
Wikunia

1
Việc vẽ đầu mũi tên trong matplotlib rất khó và hiện không được hỗ trợ trong NetworkX. Yêu cầu kéo được chấp nhận.
Back2Basics

33

Thay vì nx.draw thông thường, bạn có thể muốn sử dụng:

nx.draw_networkx(G[, pos, arrows, with_labels])

Ví dụ:

nx.draw_networkx(G, arrows=True, **options)

Bạn có thể thêm các tùy chọn bằng cách khởi tạo biến ** đó như sau:

options = {
    'node_color': 'blue',
    'node_size': 100,
    'width': 3,
    'arrowstyle': '-|>',
    'arrowsize': 12,
}

Ngoài ra một số chức năng hỗ trợ directed=True parameter Trong trường hợp này, trạng thái này là mặc định:

G = nx.DiGraph(directed=True)

Tham khảo networkx được tìm thấy ở đây .

Biểu đồ với hình ảnh mũi tên


21

Bạn cần sử dụng biểu đồ có hướng thay vì biểu đồ, tức là

G = nx.DiGraph()

Sau đó, tạo danh sách các màu cạnh bạn muốn sử dụng và chuyển các màu đó cho nx.draw(như được hiển thị bởi @Marius).

Đặt tất cả những điều này lại với nhau, tôi nhận được hình ảnh bên dưới. Vẫn không hoàn toàn là bức ảnh khác mà bạn hiển thị (tôi không biết trọng lượng các cạnh của bạn đến từ đâu), nhưng gần hơn nhiều! Nếu bạn muốn kiểm soát nhiều hơn cách đồ thị đầu ra của mình trông như thế nào (ví dụ: lấy các đầu mũi tên giống như mũi tên), tôi sẽ kiểm tra NetworkX với Graphviz .

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


Xin chúc mừng, tôi không thể tìm ra lý do tại sao các mũi tên không hoạt động vì tôi có thể thấy các đối số cho chúng trong tài liệu.
Marius

9
import networkx as nx
import matplotlib.pyplot as plt

g = nx.DiGraph()
g.add_nodes_from([1,2,3,4,5])
g.add_edge(1,2)
g.add_edge(4,2)
g.add_edge(3,5)
g.add_edge(2,3)
g.add_edge(5,4)

nx.draw(g,with_labels=True)
plt.draw()
plt.show()

Đây chỉ là cách đơn giản để vẽ đồ thị có hướng bằng python 3.x bằng networkx. chỉ là biểu diễn đơn giản và có thể được sửa đổi và tô màu, v.v. Xem biểu đồ được tạo tại đây .

Lưu ý: Nó chỉ là một đại diện đơn giản. Các cạnh có trọng số có thể được thêm vào như

g.add_edges_from([(1,2),(2,5)], weight=2)

và do đó âm mưu một lần nữa.


1
import networkx as nx
import matplotlib.pyplot as plt

G = nx.DiGraph()
G.add_node("A")
G.add_node("B")
G.add_node("C")
G.add_node("D")
G.add_node("E")
G.add_node("F")
G.add_node("G")
G.add_edge("A","B")
G.add_edge("B","C")
G.add_edge("C","E")
G.add_edge("C","F")
G.add_edge("D","E")
G.add_edge("F","G")

print(G.nodes())
print(G.edges())

pos = nx.spring_layout(G)

nx.draw_networkx_nodes(G, pos)
nx.draw_networkx_labels(G, pos)
nx.draw_networkx_edges(G, pos, edge_color='r', arrows = True)

plt.show()
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.