python'da networkx kullanarak yönlendirilmiş grafikler nasıl çizilir?


102

Bir grafiğe eşlemek istediğim bir komut dosyasından gelen bazı düğümlerim var. Aşağıda, A'dan D'ye gitmek için Arrow'u kullanmak ve muhtemelen kenarın çok renkli olmasını (kırmızı veya başka bir şey) istiyorum.

Bu temelde, diğer tüm düğümler mevcut olduğunda A'dan D'ye bir yol gibidir. her bir noktayı şehirler olarak hayal edebilirsiniz ve A'dan D'ye seyahat etmek yön (ok başlarıyla) gerektirir.

Aşağıdaki kod, grafiği oluşturur

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

ama resimde gösterildiği gibi bir şey istiyorum.görüntü açıklamasını buraya girin görüntü açıklamasını buraya girin

İlk resmin ok uçları ve kırmızı renkli kenarlar ikinci resmin üzerine.

Yanıtlar:


86

Yalnızca kırmızı kenarlar için oklarla tamamen açıklanmış örnek:

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

Kırmızı kenarlar


1
Güncellenen iki görselimizin bu kadar farklı olması çılgınca. Kenar renklerini bulmak için +1!
mdml

Yukarıdaki kodunuza göre kırmızı olması gerektiği halde kenarınız (C, E) neden kırmızı değil?
beyin fırtınası

bu ok uçlarının sadece ilgi alanlarına yerleştirilmesi mümkün değil mi? örneğin (A, C) ve (C, E)
beyin fırtınası

@ user1988876: Ah, üzgünüm, (C, E)kırmızı değil çünkü red_edgeshala yönsüz grafiğinizle çalıştığım zamanlar için kenarları seçtim , sadece dönen kenarlardan rastgele seçtim G.edges(). Olmalı red_edges = [('A', 'C'), ('E', 'C')].
Marius

@ user1988876: Sadece bazı kenarlarda oklara sahip olmak ayrı çağrılarla mümkündür draw_networkx_edges(). Kodu temizledim ve DiGraph sorunlarını düzelttim.
Marius

47

Bunu sadece eksiksizlik için koydum. Marius ve mdml'den çok şey öğrendim. İşte kenar ağırlıkları. Oklar için üzgünüm. Görünüşe göre yardım edilemez diyen tek kişi ben değilim. Bunu ipython not defteri ile işleyemedim, doğrudan python'dan gitmek zorunda kaldım, bu da kenar ağırlıklarımı daha erken almamdaki problemdi.

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

görüntü açıklamasını buraya girin


9
Bunu çalıştırdım ve düğüm etiketlerini almadım. Bu eklemek gerekir: node_labels = {node:node for node in G.nodes()}; nx.draw_networkx_labels(G, pos, labels=node_labels).
MadeOfAir

Ya zaten yönlendirilmemiş bir grafiğiniz varsa ve bunun yönlendirilmiş bir kopyasını yeniden oluşturmak istiyorsanız? G.add_edges_from()Başlangıç ​​ve bitiş noktasını manuel olarak girmek zorunda kalmadan hattı ayarlamanın herhangi bir yolu var mı ? Belki a'dan kenarlar eklemek dict?
FaCoffee

Bu bölümdeki ilk kod satırı (içe aktarma çizgileri hariç), ne tür bir grafik olduğunu ve ne tür kenarları kabul ettiğini belirler. Bir digraftan (daha fazla bilgi) bir grafiğe (daha az bilgi) gidebilirsiniz, ancak bir bilgi olmadan veya bu eksik bilgiyi oluşturmanın bir yolu olmadan bir grafikten (daha az bilgi) bir digrafa (daha fazla bilgi) gidemezsiniz. Sorunuzu başka bir yığın taşması sorusunda bir örnekle sormanızı öneririm.
Back2Basics

1
Kenarlarda gerçek oklar elde etmek mümkün mü? Sadece kalın sondan hoşlanmıyorum.
Wikunia

1
Matplotlib'de ok uçlarının çizilmesi zordur ve şu anda NetworkX'te desteklenmemektedir. Çekme istekleri kabul edilir.
Back2Basics

33

Normal nx.draw yerine kullanmak isteyebilirsiniz:

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

Örneğin:

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

Bu ** değişkeni şu şekilde başlatarak seçenekler ekleyebilirsiniz:

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

Ayrıca bazı işlevler directed=True parameter şunları destekler: Bu durumda bu durum varsayılan durumdur:

G = nx.DiGraph(directed=True)

Networkx referansı burada bulunur .

Ok resmi olan grafik


21

Grafik yerine yönlendirilmiş bir grafik kullanmanız gerekir , yani

G = nx.DiGraph()

Ardından, kullanmak istediğiniz kenar renklerinin bir listesini oluşturun ve bunları nx.drawiletin (@Marius tarafından gösterildiği gibi).

Tüm bunları bir araya getirerek aşağıdaki resmi elde ediyorum. Yine de gösterdiğiniz diğer resim değil (kenar ağırlıklarınızın nereden geldiğini bilmiyorum), ama çok daha yakın! Çıktı grafiğinizin nasıl göründüğüne dair daha fazla kontrol istiyorsanız (örneğin oklara benzeyen ok başları elde edin), Graphviz ile NetworkX'e bakarım .

görüntü açıklamasını buraya girin


Ah şerefe, belgelerde onlar için argümanlar görebildiğim için okların neden işe yaramadığını anlayamadım.
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()

Networkx kullanarak python 3.x kullanarak yönlendirilmiş grafiğin nasıl çizileceği bu kadar basittir. sadece basit gösterimdir ve değiştirilebilir ve renklendirilebilir vb. Oluşturulan grafiğe buradan bakın .

Not: Bu sadece basit bir temsildir. Ağırlıklı Kenarlar gibi eklenebilir

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

ve dolayısıyla yeniden çizildi.


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()
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.