Wie zeichnet man mit networkx in Python gerichtete Graphen?

101

Ich habe einige Knoten aus einem Skript, die ich einem Diagramm zuordnen möchte. Im Folgenden möchte ich Arrow verwenden, um von A nach D zu gelangen, und wahrscheinlich habe ich auch die Kante eingefärbt (rot oder so).

Dies ist im Grunde wie ein Pfad von A nach D, wenn alle anderen Knoten vorhanden sind. Sie können sich jeden Knoten als Städte vorstellen. Für die Fahrt von A nach D sind Anweisungen erforderlich (mit Pfeilspitzen).

Dieser Code unten erstellt das Diagramm

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

aber ich möchte so etwas wie im Bild gezeigt.Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

Pfeilspitzen des ersten Bildes und die Kanten in roter Farbe auf das zweite Bild.

Brainstorming
quelle

Antworten:

86

Vollständig ausgearbeitetes Beispiel mit Pfeilen nur für die roten Ränder:

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

Rote Ränder

Marius
quelle
1
Es ist verrückt, wie unterschiedlich unsere beiden aktualisierten Bilder sind. +1 für das Herausfinden der Kantenfarben!
Mdml
Warum ist Ihre Kante (C, E) nicht rot, obwohl sie gemäß dem obigen Code rot sein muss?
Brain Storm
Ist es nicht möglich, diese Pfeilspitzen nur an interessierenden Kanten zu haben? beispielsweise (A, C) und (C, E)
Brain Storm
@ user1988876: Ah, tut mir leid, (C, E)ist nicht rot, weil ich die Kanten ausgewählt habe, red_edgesals ich noch mit Ihrem ungerichteten Diagramm gearbeitet habe, sondern nur zufällig aus den von zurückgegebenen Kanten ausgewählt habe G.edges(). Es sollte sein red_edges = [('A', 'C'), ('E', 'C')].
Marius
@ user1988876: Mit separaten Aufrufen von können nur Pfeile an einigen Kanten angezeigt werden draw_networkx_edges(). Ich habe den Code bereinigt und die DiGraph-Probleme behoben.
Marius
46

Ich habe dies nur der Vollständigkeit halber angegeben. Ich habe viel von Marius und Mdml gelernt. Hier sind die Kantengewichte. Entschuldigung für die Pfeile. Sieht so aus, als wäre ich nicht der einzige, der sagt, dass nicht geholfen werden kann. Ich konnte dies mit ipython notebook nicht rendern. Ich musste direkt von Python gehen, was das Problem war, meine Kantengewichte früher zu bekommen.

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

Geben Sie hier die Bildbeschreibung ein

Back2Basics
quelle
9
Ich habe dies ausgeführt und die Knotenbezeichnungen nicht erhalten. Sie müssen diese hinzufügen : node_labels = {node:node for node in G.nodes()}; nx.draw_networkx_labels(G, pos, labels=node_labels).
MadeOfAir
Und was ist, wenn Sie bereits ein ungerichtetes Diagramm haben und eine gerichtete Kopie davon reproduzieren möchten? Gibt es eine Möglichkeit, die G.add_edges_from()Linie festzulegen, ohne den Start- und Endpunkt manuell eingeben zu müssen? Vielleicht Kanten von a hinzufügen dict?
FaCoffee
In der ersten Codezeile in diesem Abschnitt (außer den Importzeilen) wird festgelegt, um welche Art von Diagramm es sich handelt und welche Art von Kanten akzeptiert werden. Sie können von einem Digraphen (mehr Informationen) zu einem Diagramm (weniger Informationen) wechseln, aber Sie können nicht von einem Diagramm (weniger Informationen) zu einem Digraphen (mehr Informationen) wechseln, ohne die Informationen oder eine Möglichkeit, diese fehlenden Informationen zu erstellen. Ich würde vorschlagen, Ihre Frage mit einem Beispiel in eine andere Stapelüberlauffrage aufzunehmen.
Back2Basics
1
Ist es möglich, echte Pfeile an den Kanten zu bekommen? Ich mag das nur dickere Ende nicht.
Wikunia
1
Das Zeichnen von Pfeilspitzen in matplotlib ist schwierig und wird derzeit in NetworkX nicht unterstützt. Pull-Anfragen werden akzeptiert.
Back2Basics
33

Anstelle von regulärem nx.draw möchten Sie möglicherweise Folgendes verwenden:

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

Beispielsweise:

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

Sie können Optionen hinzufügen, indem Sie diese ** Variable wie folgt initialisieren:

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

Auch einige Funktionen unterstützen die directed=True parameter In diesem Fall wird dieser Zustand ist der Standard ein:

G = nx.DiGraph(directed=True)

Die networkx-Referenz finden Sie hier .

Grafik mit Pfeilen Bild

Raz
quelle
21

Sie müssen ein gerichtetes Diagramm anstelle eines Diagramms verwenden, d. H.

G = nx.DiGraph()

Erstellen Sie dann eine Liste der Kantenfarben, die Sie verwenden möchten, und übergeben Sie diese an nx.draw Kantenfarben, die (wie von @Marius gezeigt).

Wenn ich das alles zusammenstelle, bekomme ich das Bild unten. Immer noch nicht ganz das andere Bild, das Sie zeigen (ich weiß nicht, woher Ihre Kantengewichte kommen), aber viel näher! Wenn Sie mehr Kontrolle darüber haben möchten, wie Ihr Ausgabediagramm aussieht (z. B. Pfeilspitzen, die wie Pfeile aussehen), sollten Sie NetworkX mit Graphviz ausprobieren .

Geben Sie hier die Bildbeschreibung ein

mdml
quelle
Ah Prost, ich konnte nicht herausfinden, warum Pfeile nicht funktionierten, da ich in der Dokumentation Argumente dafür sehen konnte.
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()

Dies ist nur ein einfaches Verfahren zum Zeichnen eines gerichteten Diagramms mit Python 3.x mithilfe von networkx. Nur einfache Darstellung und kann geändert und gefärbt werden usw. Siehe das generierte Diagramm hier .

Hinweis: Es ist nur eine einfache Darstellung. Gewichtete Kanten könnten wie hinzugefügt werden

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

und daher wieder geplottet.

Padmalochan Panda
quelle
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()
Sachin Rawat
quelle