Python matplotlib图例放在外侧保存时显示不完整问题解决


Posted in Python onJuly 28, 2020

上次说到的,使用如下代码保存矢量图时,放在外侧的图例往往显示不完整:

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)
 
plt.show()
 
fig.savefig('scatter.png',dpi=600)

保存为scatter.png之后的效果为:

Python matplotlib图例放在外侧保存时显示不完整问题解决

可以看到放在图像右上的图例只显示了左边一小部分。

这里的原因很简单,使用savefig()函数进行保存矢量图时,它是通过一个bounding box (bbox, 边界框),进行范围的框定,只将落入该框中的图像进行保存,如果图例没有完全落在该框中,自然不能被保存。

懂得了其原理,再进行解决问题就比较简单了。

这里有两个解决思想:

1. 将没有完全落入该bbox的图像,通过移动的方法,使其完全落入该框中,那么bbox截取的图像即是完整的 (将图像移入bbox中);

2. 改变bbox的大小,使其完全包含该图像,尤其是往往落入bbox外侧的图例 (将bbox扩大到完全包含图像)。

下面分别介绍基于这两个思想解决这个问题的两种方法:

1.  利用函数subplots_adjust()

在该官方文档中可以看到,subplots_adjust()函数的作用是调整子图布局,它包含6个参数,其中4个参数left, right, bottom, top的作用是分别调整子图的左部,右部,底部,顶部的位置,另外2个参数wspace, hspace的作用分别是调整子图之间的左右之间距离和上下之间距离。

其默认数值分别为:

Python matplotlib图例放在外侧保存时显示不完整问题解决

以上述图为例,现考虑既然图例右侧没有显示,则调整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的对比效果为: 

Python matplotlib图例放在外侧保存时显示不完整问题解决

可以看到这时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)

效果对比:

Python matplotlib图例放在外侧保存时显示不完整问题解决

图例legend在其它位置同理。 

2. 利用函数savefig()

上个博客讲到,使用savefig()函数中的三个参数fname, dpi, format可用以保存矢量图,现用该函数中另一个参数bbox_inches使

未保存到图中的图例包含进来。

下图可以看到,bbox_inches的作用是调整图的bbox, 即bounding box(边界框)

Python matplotlib图例放在外侧保存时显示不完整问题解决

 可以看到,当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('scatter2.png',dpi=600,bbox_inches='tight')

保存为scatter2.png,下面是scatter.png, scatter1.png, scatter2.png三张图的对比:

Python matplotlib图例放在外侧保存时显示不完整问题解决

可以看到,scatter1.png,即第1种方法的思想,是将图像的右侧边界向左移动,截取该图用以保存的bbox未变;而scatter2.png,即第2种方法的思想,是直接将截取该图用以保存的bbox扩大为整个图像,而将其全部包括。

注:savefig()还有两个参数需要说明

其中一个是pad_inches,它的作用是当前面的bbox_inches为'tight'时,调整图像和bbox之间的填充距离,这里不需要设置,只要选择默认值即可。

Python matplotlib图例放在外侧保存时显示不完整问题解决

个人认为,如果设置pad_inches参数为0,即pad_inches=0,截取图进行保存的bbox就是minimum bounding box (最小边界框)。 

另外一个是bbox_extra_artists,它的作用是计算图像的bbox时,将其它的元素也包含进去。

Python matplotlib图例放在外侧保存时显示不完整问题解决

这里举个例子,如果在图像左侧再加一个文本框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')

显示效果:

Python matplotlib图例放在外侧保存时显示不完整问题解决

 为防止有的元素没有被包含在bbox中,可以考虑使用该参数

到此这篇关于Python matplotlib图例放在外侧保存时显示不完整问题解决的文章就介绍到这了,更多相关matplotlib外侧保存显示不完整内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python发腾讯微博代码分享
Jan 10 Python
《Python学习手册》学习总结
Jan 17 Python
pandas求两个表格不相交的集合方法
Dec 08 Python
Python和Go语言的区别总结
Feb 20 Python
pandas计数 value_counts()的使用
Jun 24 Python
Python3.7安装keras和TensorFlow的教程图解
Jun 18 Python
python 实现二维字典的键值合并等函数
Dec 06 Python
Python netmiko模块的使用
Feb 14 Python
python3.8.1+selenium实现登录滑块验证功能
May 22 Python
keras实现多GPU或指定GPU的使用介绍
Jun 17 Python
python实现扫雷游戏的示例
Oct 20 Python
Python列表的深复制和浅复制示例详解
Feb 12 Python
Python 如何反方向迭代一个序列
Jul 28 #Python
Python Matplotlib简易教程(小白教程)
Jul 28 #Python
Python把图片转化为pdf代码实例
Jul 28 #Python
关于python3.7安装matplotlib始终无法成功的问题的解决
Jul 28 #Python
Python 合并拼接字符串的方法
Jul 28 #Python
Python reques接口测试框架实现代码
Jul 28 #Python
如何用Matplotlib 画三维图的示例代码
Jul 28 #Python
You might like
php判断字符串在另一个字符串位置的方法
2014/02/27 PHP
PHP中设置一个严格30分钟过期Session面试题的4种答案
2014/07/30 PHP
PHP实现动态web服务器方法
2015/07/29 PHP
php输出图像的方法实例分析
2017/02/16 PHP
asp 取文本框名称代码
2008/12/02 Javascript
jQuery 开发者应该注意的9个错误
2012/05/03 Javascript
JS 获取浏览器和屏幕宽高等信息的实现思路及代码
2013/07/31 Javascript
使用jquery菜单插件HoverTree仿京东无限级菜单
2014/12/18 Javascript
jquery制作LED 时钟特效
2015/02/01 Javascript
Jqgrid之强大的表格插件应用
2015/12/02 Javascript
Three.js快速入门教程
2016/09/09 Javascript
基于chosen插件实现人员选择树搜索自动筛选功能
2016/09/24 Javascript
深入理解vue-loader如何使用
2017/06/06 Javascript
vue中如何实现变量和字符串拼接
2017/06/19 Javascript
深入理解Angularjs 脏值检测
2018/10/12 Javascript
vue.js自定义组件directives的实例代码
2018/11/09 Javascript
vue 使用async写数字动态加载效果案例
2020/07/18 Javascript
nuxt 每个页面head标签内容设置方式
2020/11/05 Javascript
layui使用及简单的三级联动实现教程
2020/12/01 Javascript
[52:20]VP vs VG Supermajor小组赛 B组胜者组决赛 BO3 第一场 6.2
2018/06/03 DOTA
Python常用小技巧总结
2015/06/01 Python
详解Python的Django框架中的模版相关知识
2015/07/15 Python
Python实现二叉搜索树
2016/02/03 Python
利用Python操作消息队列RabbitMQ的方法教程
2017/07/19 Python
使用requests库制作Python爬虫
2018/03/25 Python
Python3 执行Linux Bash命令的方法
2019/07/12 Python
Python实现朴素贝叶斯的学习与分类过程解析
2019/08/24 Python
HTML5 manifest离线缓存的示例代码
2018/08/08 HTML / CSS
银行实习鉴定
2013/12/13 职场文书
高中生家长会演讲稿
2014/01/14 职场文书
幼儿园大班新学期寄语
2014/01/18 职场文书
户外拓展活动方案
2014/02/11 职场文书
最美乡村医生事迹材料
2014/06/02 职场文书
党政领导班子民主生活会整改措施
2014/09/18 职场文书
2015年卫生监督工作总结
2015/05/21 职场文书
Python文件的操作示例的详细讲解
2021/04/08 Python