2017-05-10 1 views
1

Ich habe mit dem folgenden Problem zu kämpfen. Ich möchte eine kreisförmige Grafik von etwa 100 Knoten zeichnen, wo ich sie manuell positionieren muss, entsprechend einer zuvor vorgenommenen Klassifizierung. Diese Knoten haben ein zugeordnetes Label, das sie mit unterschiedlichen Textlängen beschreibt, und ich möchte dieses Label neben dem Knoten platzieren. Die folgende Grafik ist, was ich möchte zu bekommen (ich den blauen Kreis ziehen nur um zu zeigen, dass die Etiketten perfekt an der Peripherie ausgerichtet sind): https://i.stack.imgur.com/Qre0Z.pngNetzwerk-X-Knoten Etiketten relative Position

Bisher habe ich nur diese zeichnen erreicht: https://i.stack.imgur.com/U7bZG.png

Hier

ist die MWE:

import numpy as np 
import networkx as nx 
import matplotlib.pyplot as plt 

n = 7 
G = nx.complete_graph(n) 
node_list = sorted(G.nodes()) 
angle = [] 
angle_dict = {} 
for i, node in zip(xrange(n),node_list): 
    theta = 2.0*np.pi*i/n 
    angle.append((np.cos(theta),np.sin(theta))) 
    angle_dict[node] = theta 
pos = {} 
for node_i, node in enumerate(node_list): 
    pos[node] = angle[node_i] 

labels = {0:'zero',1:'oneone',2:'twotwo',3:'threethreethree',4:'fourfourfourfour',5:'fivefivefivefivefive',6:'sixsixsixsixsixsix'} 

# figsize is intentionally set small to condense the graph 
f = plt.figure(figsize=(2,2)) 
r = f.canvas.get_renderer() 
plt.axis('equal') 
nx.draw(G,pos=pos,with_labels=True) 
description = nx.draw_networkx_labels(G,pos,labels=labels) 
for node, t in description.items(): 
    t.set_rotation(angle_dict[node]*360.0/(2.0*np.pi)) 
plt.show() 

ich glaube, ich muss hinzufügen, und spielen mit

x, y = t.get_position() 
bb = t.get_window_extent(renderer=r) 
radius = 1.0+2.0*bb.width/r.width 
t.set_position((radius*x,radius*y)) 

in der Schleife, wo ich die Rotation der Etiketten einstellen. Ich finde jedoch nicht heraus, wie man es richtig einstellt und wie man vermeidet, die Leinwand zu beschneiden.

Antwort

2

Um die Beschriftungen außerhalb der Achsen anzuzeigen, müssten Sie die Achsen im Vergleich zur Abbildung klein machen, z. indem man einen großen Rand um die Achsen einführt. Außerdem müssen Sie den Clip-Status des Texts festlegen, damit er nicht von den Achsen abgeschnitten wird.

Positionierung der Etiketten entsprechend der Breite des Begrenzungskastens erfordern würde, um den Begrenzungsrahmen von der Anzeige von Koordinaten, um Daten zu transformieren Koordinaten zuerst.

Komplettlösung:

import numpy as np 
import networkx as nx 
import matplotlib.pyplot as plt 

n = 7 
G = nx.complete_graph(n) 
node_list = sorted(G.nodes()) 
angle = [] 
angle_dict = {} 
for i, node in zip(xrange(n),node_list): 
    theta = 2.0*np.pi*i/n 
    angle.append((np.cos(theta),np.sin(theta))) 
    angle_dict[node] = theta 
pos = {} 
for node_i, node in enumerate(node_list): 
    pos[node] = angle[node_i] 

labels = {0:'zero',1:'oneone',2:'twotwo',3:'threethreethree',4:'fourfourfourfour',5:'fivefivefivefivefive',6:'sixsixsixsixsixsix'} 

# figsize is intentionally set small to condense the graph 
fig, ax = plt.subplots(figsize=(5,5)) 
margin=0.33 
fig.subplots_adjust(margin, margin, 1.-margin, 1.-margin) 
ax.axis('equal') 

nx.draw(G,pos=pos,with_labels=True, ax=ax) 
description = nx.draw_networkx_labels(G,pos,labels=labels) 

r = fig.canvas.get_renderer() 
trans = plt.gca().transData.inverted() 
for node, t in description.items(): 
    bb = t.get_window_extent(renderer=r) 
    bbdata = bb.transformed(trans) 
    radius = 1.2+bbdata.width/2. 
    position = (radius*np.cos(angle_dict[node]),radius* np.sin(angle_dict[node])) 
    t.set_position(position) 
    t.set_rotation(angle_dict[node]*360.0/(2.0*np.pi)) 
    t.set_clip_on(False) 

plt.show() 

enter image description here

+0

Wenn Sie mit der Art und Weise weitergehen ich die Knoten bis zu zum Beispiel der Kennzeichnung wurde, 'n = 10', so _ (null, eins, twotwo , ..., ninennineninenineninenineninen) _ und Sie speichern die Figur mit 'plt.savegig', die gespeicherte Figur wird beschnitten. Was sollte dem Code hinzugefügt werden, um das Zuschneiden zu vermeiden? – adriaat

+0

Es ist das Zusammenspiel zwischen der Figurengröße 'figsize = (5,5)' und dem Rand, den Sie anpassen müssen. Abbildung Größe kann auch automatisch für die gespeicherte Zahl skaliert werden mit dem 'bbox_inches =„tight“' Argument. Sie können auch die Schriftgröße verringern. Alles hängt davon ab, was Sie anstreben. – ImportanceOfBeingErnest

Verwandte Themen