如何在Matplotlib中放置带注释的圆形?

9
我使用matplotlib绘制了由networkx创建的图表。现在,我想在特定节点周围添加注释和圆形。例如,

enter image description here

我使用以下代码与 plt.annotate(*args, **kwargs) 一起使用:

# add annotate text
pos = nx.get_node_attributes(G, 'pos')
pos_annotation_node = pos['Medici']
ax2.annotate('Midici', 
            xy=pos_annotation_node, 
            xytext=(i+0.2 for i in pos_annotation_node),
            color='blue',
            arrowprops=dict(facecolor='blue', shrink=0.01)
        )

我得到了这张丑陋的图表,

enter image description here

我有两个问题:

  • 如何像第一张图中所示,在节点6周围画一个圆。
  • 为了得到一个好看的图形,我需要手动设置xytext的值很多次。有更好的方法吗?
3个回答

11
如果您像annotation_demo2中演示的那样使用fancyarrow arrowprops语法,那么有一个shrinkAshrinkB选项,可以让您分别缩小箭头尾部(shrinkA)和箭头尖端(shrinkB),单位为点。以下是一些任意设置代码:
import matplotlib.pyplot as plt
import numpy as np

# Some data:
dat = np.array([[5, 3, 4, 4, 6],
                [1, 5, 3, 2, 2]])

# This is the point you want to point out
point = dat[:, 2]

# Make the figure
plt.figure(1, figsize=(4, 4))
plt.clf()
ax = plt.gca()
# Plot the data
ax.plot(dat[0], dat[1], 'o', ms=10, color='r')
ax.set_xlim([2, 8])
ax.set_ylim([0, 6])

这里是将圆圈放在其中一个点周围并绘制仅在箭头顶部缩回的箭头的代码:
circle_rad = 15  # This is the radius, in points
ax.plot(point[0], point[1], 'o',
        ms=circle_rad * 2, mec='b', mfc='none', mew=2)
ax.annotate('Midici', xy=point, xytext=(60, 60),
            textcoords='offset points',
            color='b', size='large',
            arrowprops=dict(
                arrowstyle='simple,tail_width=0.3,head_width=0.8,head_length=0.8',
                facecolor='b', shrinkB=circle_rad * 1.2)
)

请注意:
1)我使用了mfc='none'将圆的标记面颜色设为透明,并将圆的大小(直径)设置为两倍半径。
2)我将箭头缩小了120%的圆半径,这样它就稍微远离了圆。显然,您可以根据需要调整circle_rad1.2的值。
3)我使用了“fancy”语法,在字符串中定义了几个箭头属性,而不是在字典中定义。据我所知,如果您不使用fancy箭头语法,则shrinkB选项不可用。
4)我使用了textcoords='offset points',以便我可以相对于点指定文本的位置,而不是绝对于坐标轴。

enter image description here


4

如何在第一张图中所示,在节点6周围画圆。

获取节点#6的中心(元组pos),并使用此数据设置蓝色圆圈的位置。

为了得到一个美观的图形,我需要手动设置xytext的值很多次。有更好的方法吗?

创建一个标签列表并遍历它以及节点坐标元组,以发布注释文本。查看代码的注释。

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from matplotlib.patches import Circle
import matplotlib.patches as patches
import numpy as np
from matplotlib.font_manager import FontProperties
font = FontProperties()
font.set_weight('bold')
font.set_size('medium')

labels = ["Midici","Firenze"]

image = mpimg.imread("g.png") # just a image of your graph
plt.imshow(image)
ax = plt.gca()

# set your own radius and centers of circles in loop, like here
r = 11; c = (157,177)
circ1 = patches.Circle(c,2*r,lw=3.,ec='b',fill=False)
ax.add_artist(circ1)
circ1.set_clip_box(ax.bbox)

# annotate circles
# I have one circle but for your array pos_annotation_node
# you need 'i' to extract proper position
for i,label in enumerate(labels):
    annot_array_end = (c[0], c[1]+2*(-1)**i*r)
    annot_text_pos = (c[0]+3,c[1]+5*(-1)**i*r)
    ax.annotate(label, 
     xy= annot_array_end, 
     xytext=annot_text_pos,
     color='b',
     fontproperties=font,
     arrowprops=dict(fc='b', shrink=.005)
    )

plt.show()

enter image description here


1

对于其他人发现这个线程,只是一个观察。并不是所有的东西都必须在Matplotlib中完成。

使用绘图包可能更容易,将您的网络图表保存为PDF(或PNG)作为背景...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接