简体   繁体   English

NetworkX节点标签的相对位置

[英]NetworkX node labels relative position

I am struggling with the following problem. 我正在努力解决以下问题。 I want to plot a circular graph of about 100 nodes where I have to manually position them, according to a classification done previously. 我想绘制一个大约100个节点的圆形图,我必须根据之前的分类手动定位它们。 These nodes have an assigned label which describes them, with different text lengths, and I want to put this label adjacent to the node. 这些节点有一个指定的标签,用不同的文本长度描述它们,我想把这个标签放在节点附近。 The following graph is what I would want to obtain (I draw the blue circle only to show that the labels are perfectly aligned at the periphery): https://i.stack.imgur.com/Qre0Z.png 下图是我想要获得的(我绘制蓝色圆圈只是为了表明标签在外围完美对齐): https//i.stack.imgur.com/Qre0Z.png

So far I have only achieved to draw this: https://i.stack.imgur.com/U7bZG.png 到目前为止,我只是画了这个: https//i.stack.imgur.com/U7bZG.png

Here is the MWE: 这是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()

I guess I have to add and play with 我想我必须添加和玩

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 the loop where I set the rotation of the labels. 在我设置标签旋转的循环中。 However, I don't figure out how to set it properly as well as how to avoid to crop the canvas. 但是,我不知道如何正确设置它以及如何避免裁剪画布。

In order to show the labels outside the axes, you would need to make the axes small compared to the figure, eg by introducing a large margin around the axes. 为了显示轴外的标签,您需要使轴与图相比较小,例如通过在轴周围引入大的余量。 You would also need to set the clip state of the text, such that it's not cut off by the axes. 您还需要设置文本的剪辑状态,以使其不被轴切断。

Positioning the labels according to the width of the bounding box would require to transform the bounding box from display coodinates to data coordinates first. 根据边界框的宽度定位标签需要首先将边界框从显示坐标转换为数据坐标。

Complete solution: 完整解决方案

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

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM