як малювати спрямовані графіки за допомогою networkx в python?


101

У мене є вузли, що надходять із сценарію, який я хочу відобразити на графіку. Нижче я хочу використовувати стрілку для переходу від A до D і, ймовірно, край теж забарвлений (червоний або щось подібне).

Це в основному, як шлях від А до 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')].
Маріус

@ user1988876: Показ стрілок лише на деяких краях можливий за допомогою окремих викликів на draw_networkx_edges(). Я очистив код і виправив проблеми DiGraph.
Маріус

47

Я вкладаю це лише для повноти. Я багато чого навчився з маріусу та 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

Перший рядок коду в цьому розділі (окрім рядків імпорту) встановлює, який тип графіку це та які ребра він приймає. Ви можете перейти від диграфа (більше інформації) до графіка (менше інформації), але ви не можете перейти від графіка (менше інформації) до диграфа (більше інформації) без інформації або способу побудови цієї відсутньої інформації. Я б запропонував поставити ваше запитання на прикладі в іншому запитанні про переповнення стека.
Назад2Basics

1
Чи можна отримати справжні стрілки по краях? Мені не подобається просто товстіший кінець.
Вікунія

1
Малювання стрілок із стрілок у matplotlib є складним і наразі не підтримується в NetworkX. Запити на витяг приймаються.
Назад2Basics

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 .

введіть тут опис зображення


Ну привіт, я не міг зрозуміти, чому стрілки не працюють, як я міг бачити аргументи для них у документації.
Маріус

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()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.