在 Matplotlib 中绘制椭圆以注释绘图

问题描述

我最近发现 matplotlib 作为 Matlab 的更好的绘图替代品。不幸的是,我对 Python 的了解几乎为零。

考虑下图和相关代码

import numpy as np
import scipy.io
from matplotlib import pyplot as plt

plt.figure(figsize=[3.3,3.3])
plt.rcParams.update({'font.size': 8,'text.usetex': True})

plt.plot([1,2,3,4],[1,4,9,16],color='r')
plt.plot([1,[2,5,10,17],[11,14,19,26],color='b')
plt.plot([1,[12,15,20,27],color='b')

plt.annotate('blue curves',xy=(1.5,22.5),xytext=(1.5,ha='center',va='center')
plt.annotate('',xy=(2,15),22),arrowprops=dict(width=0.1,headwidth=2,headlength=2,color='grey'))
plt.annotate('red curves',xy=(2.5,xytext=(2.5,xy=(3,10),color='grey'))

plt.grid()
plt.xlabel('x')
plt.ylabel('y')

plt.savefig('filename.pdf',format='pdf')

plt.show()

enter image description here

我想为包围曲线的每个箭头添加一个小椭圆/圆。椭圆/圆应具有相同的箭头样式(即颜色、粗细等)。有没有一种简单的方法可以在不修改大量现有代码的情况下做到这一点?

我试图从 this example 中获得一些灵感,但没有奏效。

解决方法

一个简单的解决方案,如果一个圆圈很好,就是在箭头的位置添加一个散点(我没有安装LaTex):

import numpy as np
import scipy.io
from matplotlib import pyplot as plt

plt.figure(figsize=[3.3,3.3],dpi=100)
plt.rcParams.update({'font.size': 8,'text.usetex': False})

plt.plot([1,2,3,4],[1,4,9,16],color='r')
plt.plot([1,[2,5,10,17],[11,14,19,26],color='b')
plt.plot([1,[12,15,20,27],color='b')

plt.annotate('blue curves',xy=(1.5,22.5),xytext=(1.5,ha='center',va='center')
plt.annotate('',xy=(2,15),22),arrowprops=dict(width=0.1,headwidth=2,headlength=2,color='grey'))
plt.annotate('red curves',xy=(2.5,xytext=(2.5,xy=(3,10),color='grey'))

plt.plot(2,'o',ms=10 * 2,mec='grey',mfc='none',mew=1.5)
plt.plot(3,mew=1.5)

plt.grid()
plt.xlabel('x')
plt.ylabel('y')

plt.savefig('filename.pdf',format='pdf')

plt.show()

enter image description here

,

虽然您可以在 plot 对象上调用 annotateplt,但您需要访问 figureaxishere 很好地解释了绘图、图形和轴之间的差异。

您必须添加的代码(在 plt.show() 之前):

from matplotlib.patches import Ellipse

fig = plt.gcf()  # access the current figure
ax = plt.gca()   # access the current axis
xmin,xmax = ax.get_xlim()  # get the minimum and maximum extent of the x-axis
ymin,ymax = ax.get_ylim()  # get the minimum and maximum extent of the y-axis
aspect_ratio = fig.get_figheight() / fig.get_figwidth()  # get aspect ratio,we will use it to scale the width and height of the ellipse to appear as a circle
ax.add_patch(Ellipse(xy=(2,width=(xmax-xmin)*aspect_ratio/5,height=(ymax-ymin)/5,color="grey",fill=False,lw=2))
ax.add_patch(Ellipse(xy=(3,lw=2))

enter image description here