วิธีการวาดกราฟกำกับโดยใช้ networkx ใน python


102

ฉันมีโหนดที่มาจากสคริปต์ที่ฉันต้องการแมปกับกราฟ ด้านล่างนี้ฉันต้องการใช้ลูกศรเพื่อเปลี่ยนจาก A ไป D และอาจมีขอบสีด้วย (สีแดงหรือบางอย่าง)

โดยพื้นฐานแล้วก็เหมือนกับเส้นทางจาก A ไป D เมื่อมีโหนดอื่น ๆ ทั้งหมด คุณสามารถจินตนาการว่าแต่ละโหนดเป็นเมืองและการเดินทางจาก A ถึง D ต้องใช้เส้นทาง (ด้วยหัวลูกศร)

โค้ดด้านล่างนี้สร้างกราฟ

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

แต่ฉันต้องการสิ่งที่เหมือนที่แสดงในภาพป้อนคำอธิบายภาพที่นี่ ป้อนคำอธิบายภาพที่นี่

หัวลูกศรของภาพแรกและขอบเป็นสีแดงบนภาพที่สอง

คำตอบ:


86

ตัวอย่างที่เต็มไปด้วยลูกศรสำหรับขอบสีแดงเท่านั้น:

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

ขอบสีแดง


1
มันบ้ามากแค่ไหนภาพที่อัปเดตของเราสองภาพนั้นแตกต่าง +1 สำหรับการหาสีขอบ!
mdml

เหตุใดขอบของคุณ (C, E) จึงไม่เป็นสีแดงแม้ว่าจะต้องเป็นสีแดงตามรหัสของคุณด้านบน?
พายุสมอง

เป็นไปไม่ได้ที่จะมีหัวลูกศรเหล่านี้เฉพาะบนขอบที่น่าสนใจ? ตัวอย่างเช่น (A, C) และ (C, E)
พายุสมอง

@ user1988876: อ่าขอโทษ(C, E)ไม่แดงเพราะผมหยิบขอบสำหรับตอนที่ผมยังคงทำงานร่วมกับกราฟไม่มีทิศทางของคุณเพียงแค่หยิบสุ่มจากขอบที่ส่งกลับโดยred_edges มันควรจะเป็นG.edges() red_edges = [('A', 'C'), ('E', 'C')]
Marius

@ user1988876: มีลูกศรที่ขอบบางส่วนเท่านั้นที่สามารถเรียกแยกกันdraw_networkx_edges()ได้ ฉันได้ทำความสะอาดโค้ดและแก้ไขปัญหา DiGraph แล้ว
Marius

47

ฉันใส่ไว้เพื่อความสมบูรณ์เท่านั้น ฉันได้เรียนรู้มากมายจาก marius และ mdml นี่คือน้ำหนักขอบ ขออภัยเกี่ยวกับลูกศร ดูเหมือนว่าฉันไม่ใช่คนเดียวที่บอกว่าช่วยไม่ได้ ฉันไม่สามารถแสดงสิ่งนี้ด้วยโน้ตบุ๊ก ipython ฉันต้องไปจาก python โดยตรงซึ่งเป็นปัญหาในการรับน้ำหนักขอบของฉันเร็วกว่านั้น

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

ป้อนคำอธิบายภาพที่นี่


9
ฉันเรียกใช้สิ่งนี้และไม่ได้รับป้ายชื่อโหนด node_labels = {node:node for node in G.nodes()}; nx.draw_networkx_labels(G, pos, labels=node_labels)คุณต้องเพิ่มเหล่านี้:
MadeOfAir

และจะเกิดอะไรขึ้นถ้าคุณมีกราฟที่ไม่ได้บอกทิศทางและต้องการสร้างสำเนากำกับมันขึ้นมาใหม่? มีวิธีการตั้งค่าG.add_edges_from()เส้นโดยไม่ต้องป้อนจุดเริ่มต้นและจุดสิ้นสุดด้วยตนเองหรือไม่? อาจจะเพิ่มขอบจากdict?
FaCoffee

โค้ดบรรทัดแรกในส่วนนี้ (นอกเหนือจากบรรทัดนำเข้า) กำหนดประเภทของกราฟและประเภทของขอบที่ยอมรับได้ คุณสามารถเปลี่ยนจากกราฟ (ข้อมูลเพิ่มเติม) ไปยังกราฟ (ข้อมูลน้อยกว่า) แต่คุณไม่สามารถเปลี่ยนจากกราฟ (ข้อมูลน้อย) ไปยังไดกราฟ (ข้อมูลเพิ่มเติม) โดยไม่มีข้อมูลหรือวิธีสร้างข้อมูลที่ขาดหายไป ฉันขอแนะนำให้ใส่ตัวอย่างคำถามของคุณในคำถามอื่น ๆ
Back2Basics

1
เป็นไปได้ไหมที่จะได้รับลูกศรจริงที่ขอบ? ฉันไม่ชอบปลายที่หนาขึ้น
Wikunia

1
การวาดหัวลูกศรใน matplotlib นั้นยุ่งยากและปัจจุบัน NetworkX ยังไม่รองรับ ยอมรับคำขอดึง
Back2Basics

33

แทนที่จะใช้ nx.draw ปกติคุณอาจต้องการใช้:

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

ตัวอย่างเช่น:

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

คุณสามารถเพิ่มตัวเลือกได้โดยการเริ่มต้นตัวแปร ** ดังนี้:

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

นอกจากนี้ฟังก์ชันบางอย่างยังรองรับdirected=True parameter ในกรณีนี้สถานะนี้เป็นสถานะเริ่มต้น:

G = nx.DiGraph(directed=True)

อ้างอิง networkx พบที่นี่

กราฟด้วยภาพลูกศร


21

คุณต้องใช้กราฟกำกับแทนกราฟกล่าวคือ

G = nx.DiGraph()

จากนั้นสร้างรายการสีขอบที่คุณต้องการใช้และส่งต่อไปยังnx.draw(ดังที่แสดงโดย @Marius)

รวมทั้งหมดนี้เข้าด้วยกันฉันจะได้ภาพด้านล่าง ยังไม่ใช่ภาพอื่นที่คุณแสดง (ฉันไม่รู้ว่าน้ำหนักขอบของคุณมาจากไหน) แต่ใกล้กว่ามาก! หากคุณต้องการการควบคุมมากขึ้นของวิธีการส่งออกกราฟลักษณะของคุณ (เช่นได้รับหัวลูกศรที่มีลักษณะเหมือนลูกศร) ผมตรวจสอบNetworkX กับ Graphviz

ป้อนคำอธิบายภาพที่นี่


อาไชโยฉันคิดไม่ออกว่าทำไมลูกศรถึงไม่ทำงานเพราะฉันเห็นข้อโต้แย้งของพวกเขาในเอกสารประกอบ
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()

นี่เป็นเพียงวิธีง่ายๆในการวาดกราฟกำกับโดยใช้ python 3.x โดยใช้ networkx เพียงตัวแทนที่เรียบง่ายและสามารถปรับเปลี่ยนและสีอื่น ๆ โปรดดูกราฟที่สร้างขึ้นที่นี่

หมายเหตุ: เป็นเพียงการนำเสนอธรรมดา ๆ สามารถเพิ่มขอบถ่วงน้ำหนักได้เช่น

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

และด้วยเหตุนี้จึงวางแผนอีกครั้ง


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()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.