2012-11-22 5 views
15

Ich versuche plotten/skizzieren (matplotlib oder andere Python-Bibliothek) ein 2D-Netzwerk einer großen Distanz-Matrix, wo Entfernungen die Kanten des skizzierten Netzwerks und die Linie und Spalte sein Knoten wären.Eine Grafik oder ein Netzwerk aus einer Entfernungsmatrix zeichnen?

DistMatrix = 
[  'a', 'b',  'c', 'd'], 
['a', 0,  0.3, 0.4, 0.7], 
['b', 0.3, 0,  0.9, 0.2], 
['c', 0.4, 0.9, 0,  0.1], 
['d', 0.7, 0.2, 0.1, 0] ] 

Ich suche aus dem 2D-Netzwerk zu skizzieren/Plot solchen (größer: tausend Spalten und Zeilen) Abstandsmatrix: node ‚a‘ verbunden ist, ‚b‘ durch eine Kante Tiefe von 0,3 zu dem Knoten, Die Knoten "c" und "d" wären mit einer Kantentiefe von 0,1 verknüpft. Was sind die Werkzeuge/Bibliotheken, die ich verwenden kann (Distanzmatrix kann in numpy Matrix umgewandelt werden), um die Skizze/grafische Projektion eines solchen Netzwerkes zu erhalten? (Pandas, Matplotlib, Igraph, ...?) und einige führen dazu, das schnell zu tun (ich würde meine Selbst-Tkinter-Funktion nicht dafür definieren ;-))? danke für Ihre eingehenden Antworten.

+0

Theoretisch dies für bestimmte Distanzmatrizen unmöglich sein könnte. Stellen Sie sich z.B. eine 4 x 4 Entfernungsmatrix mit allen Einträgen 1. Dies definiert einen dreidimensionalen Simplex. Es gibt keine Möglichkeit, dieses Diagramm isometrisch in zwei Dimensionen einzubetten. Was sollte das Programm in diesem Fall tun? – Turion

+0

rechts, also keine "Kantenlänge" sondern "Kantentiefe, die zwei Knoten verbindet – sol

Antwort

21

Das graphviz Programm neatoversucht Kantenlängen einzuhalten. doug shows a way nutzen neatonetworkx wie folgt aus:

import networkx as nx 
import numpy as np 
import string 

dt = [('len', float)] 
A = np.array([(0, 0.3, 0.4, 0.7), 
       (0.3, 0, 0.9, 0.2), 
       (0.4, 0.9, 0, 0.1), 
       (0.7, 0.2, 0.1, 0) 
       ])*10 
A = A.view(dt) 

G = nx.from_numpy_matrix(A) 
G = nx.relabel_nodes(G, dict(zip(range(len(G.nodes())),string.ascii_uppercase)))  

G = nx.drawing.nx_agraph.to_agraph(G) 

G.node_attr.update(color="red", style="filled") 
G.edge_attr.update(color="blue", width="2.0") 

G.draw('/tmp/out.png', format='png', prog='neato') 

ergibt

enter image description here

+0

Ich habe den Code, den Sie vorschlagen, ausprobiert, angepasst an meine Bedürfnisse (entfernen Sie die A.view) und es hat nicht einmal für nur 7 Knoten funktioniert. G ist korrekt. Was könnte schief gelaufen? Ich benutze graphviz 2.36. – Picarus

+1

Dies Fälle mich Fehler ''Modul' Objekt hat kein Attribut 'to_agraph''. Zur Behebung habe ich http://stackoverflow.com/questions/35279733/what -could-cause-networkx-pygraphviz-zu-arbeiten-fein-allein-aber-nicht-zusammen und stattdessen verwendet 'nx.drawing.nx_agraph.to_agraph' – kungfujam

+0

@kungfujam: Danke für das Update. – unutbu

14

Sie können das Paket networkx verwenden, das perfekt mit diesen Problemen zusammenarbeitet. Passen Sie Ihre Matrix eine einfache numpy Array wie folgt zu entfernen:

DistMatrix =array([[0,  0.3, 0.4, 0.7], 
[0.3, 0,  0.9, 0.2], 
[0.4, 0.9, 0,  0.1], 
[0.7, 0.2, 0.1, 0] ]) 

dann importieren NetworkX und es verwenden,

import networkx as nx 
G = G=nx.from_numpy_matrix(DistMatrix) 
nx.draw(G) 

, wenn Sie eine gewichtete Version des Graphen zeichnen möchten, müssen Sie die angeben Farbe jeder Kante (zumindest konnte ich nicht finden, eine automatisierte Art und Weise zu tun, es finden):

nx.draw(G,edge_color = [ i[2]['weight'] for i in G.edges(data=True) ], edge_cmap=cm.winter)