添加图例的两种方法
1.【推荐使用】在plot函数中增加label参数,然后在后面加上plt.legend()
plt.plot(x, x*3.0, label='Fast')
plt.plot(x, x/3.0, label='Slow')
plt.legend()
2.legend方法中传入字符串列表
plt.plot(x,np.sin(x),x,np.cos(x))
plt.legend(["sin","cos"])
接下来是两篇文章的阅读笔记(将自己不懂的地方标注了一下)
第一篇:
用python的matplotlib画图时,往往需要加图例说明。如果不设置任何参数,默认是加到图像的内侧的最佳位置。
如果需要将该legend移到图像外侧,有多种方法,这里介绍一种。
在plt.legend()函数中加入若干参数:plt.legend(bbox_to_anchor=(num1, num2), loc=num3, borderaxespad=num4),只要加上这些参数并给他们设置一定的值,则就会将图例放在外面。
具体设置参考文章:https://blog.csdn.net/Poul_henry/article/details/82533569
第二篇:原文链接:https://blog.csdn.net/Poul_henry/article/details/88311964
上次说到的,使用如下代码保存矢量图时,放在外侧的图例往往显示不完整:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
'''fig,ax = plt.subplots()等价于:
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
fig, ax = plt.subplots(1,3),其中参数1和3分别代表子图的行数和列数,一共有 1x3 个子图像。函数返回一个figure图像和子图ax的array列表。
fig, ax = plt.subplots(1,3,1),最后一个参数1代表第一个子图。
如果想要设置子图的宽度和高度可以在函数内加入figsize值
fig, ax = plt.subplots(1,3,figsize=(15,7)),这样就会有1行3个15x7大小的子图。 '''
x1 = np.random.uniform(-10, 10, size=20)
x2 = np.random.uniform(-10, 10, size=20)
#x1,x2是服从U(-10,10)均匀分布的随机数组
number = []
x11 = []
x12 = []
for i in range(20):
number.append(i+1)
x11.append(i+1)
x12.append(i+1)
''' 最后number , x11,x12= [1,2,..,20] '''
plt.figure(1)
#plt.figure(1)是新建一个名叫 Figure1的画图窗口
plt.plot(number, x1, 'bo', markersize=20,label='a') # blue circle with size 20
plt.plot(number, x2, 'ro', ms=10,label='b') # ms is just an alias for markersize
'''可选参数[fmt] 是一个字符串来定义图的基本属性如:颜色(color),点型(marker),线型(linestyle),
具体形式 fmt = '[color][marker][line]',fmt接收的是每个属性的单个字母缩写,例如:plot(x, y, 'bo-') # 蓝色圆点实线
所以这里的bo就是蓝色圆点,ro就是红色圆点'''
lgnd=plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0,numpoints=1,fontsize=10)
lgnd.legendHandles[0]._legmarker.set_markersize(16)
lgnd.legendHandles[1]._legmarker.set_markersize(10)
''' bbox_to_anchor:表示legend的位置,前一个表示左右,后一个表示上下。
bbox_to_anchor被赋予的二元组中,第一个数值用于控制legend的左右移动,值越大越向右边移动,
第二个数值用于控制legend的上下移动,值越大,越向上移动。
为了美观,需要将legend放于图像的外侧,而又距离不是太大,一般设num1=1.05。
loc=2 表示upper left,在左上角。
所以,当设bbox_to_anchor=(1.05,0),即legend放于图像右下角时,为美观起见,需要将legend的左下角,即'lower left'放置该点,对应该表的‘Location Code’数字为2,即参数num3置为2或直接设为‘upper left’;而当设bbox_to_anchor=(1.05,1),即legend放于图像右上角时,为美观起见,需要将legend的左上角,即'upper left'放置该点,对应该表的‘Location Code’数字为3,即参数num3置为3或直接设为‘lower left’。
borderaxespad 表示 轴和图例边框之间的填充,以字体大小距离测量,默认值为None,但实际操作中,如果不加该参数,效果是有一定的填充。等于0说明对齐。
numpoints 表示 线条图例中的点数 '''
plt.show()
fig.savefig('scatter.png',dpi=600)
保存为scatter.png之后的效果为:
可以看到放在图像右上的图例只显示了左边一小部分。
这里的原因很简单,使用savefig()函数进行保存矢量图时,它是通过一个bounding box (bbox, 边界框),进行范围的框定,只将落入该框中的图像进行保存,如果图例没有完全落在该框中,自然不能被保存。
懂得了其原理,再进行解决问题就比较简单了。
这里有两个解决思想:
-
将没有完全落入该bbox的图像,通过移动的方法,使其完全落入该框中,那么bbox截取的图像即是完整的 (将图像移入bbox中);
-
改变bbox的大小,使其完全包含该图像,尤其是往往落入bbox外侧的图例 (将bbox扩大到完全包含图像)。
下面分别介绍基于这两个思想解决这个问题的两种方法:
- 利用函数subplots_adjust()
在该官方文档中可以看到,subplots_adjust()函数的作用是调整子图布局,它包含6个参数,其中4个参数left, right, bottom, top的作用是分别调整子图的左部,右部,底部,顶部的位置,另外2个参数wspace, hspace的作用分别是调整子图之间的左右之间距离和上下之间距离。
其默认数值分别为:
以上述图为例,现考虑既然图例右侧没有显示,则调整subplots_adjust()函数的right参数,使其位置稍往左移,将参数right默认的数值0.9改为0.8,那么可以得到一个完整的图例:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
x1 = np.random.uniform(-10, 10, size=20)
x2 = np.random.uniform(-10, 10, size=20)
#print(x1)
#print(x2)
number = []
x11 = []
x12 = []
for i in range(20):
number.append(i+1)
x11.append(i+1)
x12.append(i+1)
plt.figure(1)
# you can specify the marker size two ways directly:
plt.plot(number, x1, 'bo', markersize=20,label='a') # blue circle with size 20
plt.plot(number, x2, 'ro', ms=10,label='b') # ms is just an alias for markersize
lgnd=plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0,numpoints=1,fontsize=10)
lgnd.legendHandles[0]._legmarker.set_markersize(16)
lgnd.legendHandles[1]._legmarker.set_markersize(10)
fig.subplots_adjust(right=0.8)
plt.show()
fig.savefig('scatter1.png',dpi=600)
保存为scatter1.png之后和scatter.png的对比效果为:
可以看到这时scatter1.png的图例显示完整,它是通过图像的右侧位置向左移动而被整体包含在保存的图像中完成的。
同理,若legend的位置在图像下侧,使用savefig()保存时也是不完整的,这时需要修改的是函数subplots_adjust()的参数bottom,使其向上移,而被包含在截取图像进行保存的框中,即下文介绍的bbox。
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
x1 = np.random.uniform(-10, 10, size=20)
x2 = np.random.uniform(-10, 10, size=20)
#print(x1)
#print(x2)
number = []
x11 = []
x12 = []
for i in range(20):
number.append(i+1)
x11.append(i+1)
x12.append(i+1)
plt.figure(1)
# you can specify the marker size two ways directly:
plt.plot(number, x1, 'bo', markersize=20,label='a') # blue circle with size 20
plt.plot(number, x2, 'ro', ms=10,label='b') # ms is just an alias for markersize
lgnd=plt.legend(bbox_to_anchor=(0.4, -0.1), loc=2, borderaxespad=0,numpoints=1,fontsize=10)
lgnd.legendHandles[0]._legmarker.set_markersize(16)
lgnd.legendHandles[1]._legmarker.set_markersize(10)
plt.show()
fig.savefig('scatter#1.png',dpi=600)
由于subplots_adjust()中默认的bottom值为0.1,故添加fig.subplots_adjust(bottom=0.2),使其底部上移,修改为
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
x1 = np.random.uniform(-10, 10, size=20)
x2 = np.random.uniform(-10, 10, size=20)
#print(x1)
#print(x2)
number = []
x11 = []
x12 = []
for i in range(20):
number.append(i+1)
x11.append(i+1)
x12.append(i+1)
plt.figure(1)
# you can specify the marker size two ways directly:
plt.plot(number, x1, 'bo', markersize=20,label='a') # blue circle with size 20
plt.plot(number, x2, 'ro', ms=10,label='b') # ms is just an alias for markersize
lgnd=plt.legend(bbox_to_anchor=(0.4, -0.1), loc=2, borderaxespad=0,numpoints=1,fontsize=10)
lgnd.legendHandles[0]._legmarker.set_markersize(16)
lgnd.legendHandles[1]._legmarker.set_markersize(10)
fig.subplots_adjust(bottom=0.2)
plt.show()
fig.savefig('scatter#1.png',dpi=600)
效果对比:
图例legend在其它位置同理。
- 利用函数savefig()
上个博客讲到,使用savefig()函数中的三个参数fname(文件名), dpi(分辨率), format(格式)可用以保存矢量图,现用该函数中另一个参数bbox_inches使未保存到图中的图例包含进来。
下图可以看到,bbox_inches的作用是调整图的bbox, 即bounding box(边界框)
可以看到,当bbox_inches设为’tight’时,它会计算出距该图像的较紧(tight)边界框bbox,并将该选中的框中的图像保存。
这里的较紧的边界框应该是指完全包含该图像的一个矩形,但和图像有一定的填充距离,个人认为和Minimum bounding box(最小边界框)有一定区别。单位同样是英寸(inch)。
这样图例就会被bbox包含进去,进而被保存。
完整代码:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
x1 = np.random.uniform(-10, 10, size=20)
x2 = np.random.uniform(-10, 10, size=20)
#print(x1)
#print(x2)
number = []
x11 = []
x12 = []
for i in range(20):
number.append(i+1)
x11.append(i+1)
x12.append(i+1)
plt.figure(1)
# you can specify the marker size two ways directly:
plt.plot(number, x1, 'bo', markersize=20,label='a') # blue circle with size 20
plt.plot(number, x2, 'ro', ms=10,label='b') # ms is just an alias for markersize
lgnd=plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0,numpoints=1,fontsize=10)
lgnd.legendHandles[0]._legmarker.set_markersize(16)
lgnd.legendHandles[1]._legmarker.set_markersize(10)
#fig.subplots_adjust(right=0.8)
plt.show()
fig.savefig('G:/《Python数据分析与应用》学习代码/第三章/scatter2.png',dpi=600,bbox_inches='tight')
保存为scatter2.png,下面是scatter.png, scatter1.png, scatter2.png三张图的对比:
可以看到,scatter1.png,即第1种方法的思想,是将图像的右侧边界向左移动,截取该图用以保存的bbox未变;而scatter2.png,即第2种方法的思想,是直接将截取该图用以保存的bbox扩大为整个图像,而将其全部包括。
注:savefig()还有两个参数需要说明
其中一个是pad_inches,它的作用是当前面的bbox_inches为’tight’时,调整图像和bbox之间的填充距离,这里不需要设置,只要选择默认值即可。
个人认为,如果设置pad_inches参数为0,即pad_inches=0,截取图进行保存的bbox就是minimum bounding box (最小边界框)。
另外一个是bbox_extra_artists,它的作用是计算图像的bbox时,将其它的元素也包含进去。
这里举个例子,如果在图像左侧再加一个文本框text,保存图像时希望该文本框包含在bbox中,则可以使用该参数bbox_extra_artists将text包含进去(实际使用中,即使未使用bbox_extra_artists,保存的图像也包含该text):
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
x1 = np.random.uniform(-10, 10, size=20)
x2 = np.random.uniform(-10, 10, size=20)
#print(x1)
#print(x2)
number = []
x11 = []
x12 = []
for i in range(20):
number.append(i+1)
x11.append(i+1)
x12.append(i+1)
plt.figure(1)
# you can specify the marker size two ways directly:
plt.plot(number, x1, 'bo', markersize=20,label='a') # blue circle with size 20
plt.plot(number, x2, 'ro', ms=10,label='b') # ms is just an alias for markersize
lgnd=plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0,numpoints=1,fontsize=10)
lgnd.legendHandles[0]._legmarker.set_markersize(16)
lgnd.legendHandles[1]._legmarker.set_markersize(10)
text = ax.text(-0.3,1, "test", transform=ax.transAxes)
#fig.subplots_adjust(right=0.8)
plt.show()
fig.savefig('scatter3.png',dpi=600, bbox_extra_artists=(lgnd,text),bbox_inches='tight')
显示效果:
为防止有的元素没有被包含在bbox中,可以考虑使用该参数bbox_extra_artists
来源:https://blog.csdn.net/qq_44883214/article/details/99684511