2012-10-22 4 views
8

Ich benutze Pydot, um Grafiken in Python zu zeichnen. Ich möchte einen Entscheidungsbaum vertreten, so etwas sagen wie (a1, a2, a3 sind Attribute und zwei Klassen 0 und 1:Pydot: ist es möglich, zwei verschiedene Knoten mit der gleichen Zeichenfolge in ihnen zu plotten?

 a1>3 
    / \ 
    a2>10 a3>-7 
/\ /\ 
    1 0 1 0 

jedoch mit pydot werden nur zwei Blätter erstellt und der Baum sieht wie folgt aus (png beigefügt):

 a1>3 
    / \ 
    a2>10 a3>-7 
     | X | 
     1  0 

nun in diesem einfachen Fall die Logik ist in Ordnung, aber in größeren Bäumen ist es chaotisch inneren Knoten zu verschiedenen Zweigen vereinigt sind gehören,

der einfache Code I‘. m using ist:

import pydot 
graph = pydot.Dot(graph_type='graph') 
edge = pydot.Edge("a_1>3", "a_2>10") 
graph.add_edge(edge) 
edge = pydot.Edge("a_1>3", "a_3>-7") 
graph.add_edge(edge) 
edge = pydot.Edge("a_2>10", "1") 
graph.add_edge(edge) 
edge = pydot.Edge("a_2>10", "0") 
graph.add_edge(edge) 
edge = pydot.Edge("a_3>-7", "1") 
graph.add_edge(edge) 
edge = pydot.Edge("a_3>-7", "0") 
graph.add_edge(edge) 
graph.write_png('simpleTree.png') 

Ich habe auch versucht, verschiedene Knotenobjekte zu erstellen, als die Kanten zu erstellen und dann zum Diagramm hinzuzufügen, aber es scheint, dass pydot den Knotenpool nach Knoten mit demselben Namen prüft, anstatt einen neuen zu erstellen.

Irgendwelche Ideen? Vielen Dank!

the image created by the code above

Antwort

13

Ihre Knoten benötigen immer einen eindeutigen Namen, sonst man sich nicht eindeutig benennen Kanten zwischen ihnen zu befestigen. Sie können jedoch jedem Knoten eine Beschriftung geben, die beim Rendern angezeigt wird.

So müssen Sie Knoten mit eindeutigen IDs hinzuzufügen:

graph = pydot.Dot(graph_type='graph') 
graph.add_node(pydot.Node('literal_0_0', label='0')) 
graph.add_node(pydot.Node('literal_0_1', label='0')) 
graph.add_node(pydot.Node('literal_1_0', label='1')) 
graph.add_node(pydot.Node('literal_1_1', label='1')) 

dann Graphkanten Verbinden dieser Knoten hinzufügen:

edge = pydot.Edge("a_2>10", "literal_0_0") 
graph.add_edge(edge) 
edge = pydot.Edge("a_2>10", "literal_1_0") 
graph.add_edge(edge) 
edge = pydot.Edge("a_3>-7", "literal_0_1") 
graph.add_edge(edge) 
edge = pydot.Edge("a_3>-7", "literal_1_1") 
graph.add_edge(edge) 

Zusammen mit dem Rest der Kanten Sie definiert das macht:

graph with correct edges

1

Die "kanonischen" Antwort zu bedienen das uuid Modul aus der Standardbibliothek, wie networkxdoes here.

Das ist besser als id mit Knotennamen für pydot, die die Knoten in Ihrem ursprünglichen Graphen, denn wenn (theoretisch) ein Knotenobjekt wird gelöscht entsprechen zu erstellen, während Sie Ihre pydot Graph bauen, dann ist die id won‘ t muss unbedingt einzigartig sein. Im Gegensatz dazu sind die erzeugten Objekte einzigartig, beständig und unabhängig von der Lebensdauer der ursprünglichen Knoten.

Allerdings muss etwas sehr komisch passieren, während Sie den pydot Graph erstellen, was ziemlich unwahrscheinlich ist. Der Vorteil der Verwendung von id besteht darin, dass Sie keine Zuordnung von Originalknoten zu UUID Objekten erstellen und weitergeben müssen (sodass Sie nach dem Hinzufügen der Knoten konsistent die Kanten erstellen).

Ein interessanter Fall sind verschachtelte Diagramme: zwei verschiedene Diagramme, die die gleiche hashable Objekt in networkx (sagen wir a) enthalten, dann id kann nicht mehr direkt auf dem Knoten verwendet werden. Aber in diesem Fall kann id immer noch verwendet werden, indem das Paar (Knoten, Graph) wie folgt kombiniert wird: str(id(node)) + str(id(graph)).

Verwandte Themen