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 相关文章推荐
Python3基础之list列表实例解析
Aug 13 Python
基于Python实现一个简单的银行转账操作
Mar 06 Python
python opencv实现任意角度的透视变换实例代码
Jan 12 Python
Python闭包之返回函数的函数用法示例
Jan 27 Python
python使用sqlite3时游标使用方法
Mar 13 Python
浅析python继承与多重继承
Sep 13 Python
手把手教你如何安装Pycharm(详细图文教程)
Nov 28 Python
python 实现调用子文件下的模块方法
Dec 07 Python
python 爬虫百度地图的信息界面的实现方法
Oct 27 Python
wxPython实现分隔窗口
Nov 19 Python
3分钟看懂Python后端必须知道的Django的信号机制
Jul 26 Python
Python 中的单分派泛函数你真的了解吗
Jun 22 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中防止直接访问或查看或下载config.php文件的方法
2012/07/07 PHP
php中多维数组按指定value排序的实现代码
2014/08/19 PHP
详解WordPress中分类函数wp_list_categories的使用
2016/01/04 PHP
深入理解PHP 数组之count 函数
2016/06/13 PHP
PHP数据库表操作的封装类及用法实例详解
2016/07/12 PHP
PHP读取并输出XML文件数据的简单实现方法
2017/12/22 PHP
php使用socket调用http和smtp协议实例小结
2019/07/26 PHP
namespace.js Javascript的命名空间库
2011/10/11 Javascript
JS实现模仿微博发布效果实例代码
2013/12/16 Javascript
JavaScript对Cookie进行读写操作实例
2015/07/25 Javascript
jquery模拟实现鼠标指针停止运动事件
2016/01/12 Javascript
使用vue.js制作分页组件
2016/06/27 Javascript
javascript 判断是否是微信浏览器的方法
2016/10/09 Javascript
详解一个小实例理解js原型和继承
2019/04/24 Javascript
python通过imaplib模块读取gmail里邮件的方法
2015/05/08 Python
理解Python中的With语句
2016/03/18 Python
NumPy 如何生成多维数组的方法
2018/02/05 Python
对Python中type打开文件的方式介绍
2018/04/28 Python
使用Python实现租车计费系统的两种方法
2018/09/29 Python
对pandas中两种数据类型Series和DataFrame的区别详解
2018/11/12 Python
深入解析神经网络从原理到实现
2019/07/26 Python
python文件读写代码实例
2019/10/21 Python
Python基于requests库爬取网站信息
2020/03/02 Python
基于Python编写一个计算器程序,实现简单的加减乘除和取余二元运算
2020/08/05 Python
Herschel美国官网:背包、手提袋及配件
2020/03/10 全球购物
客户经理岗位职责
2013/12/08 职场文书
秋季运动会稿件
2014/01/30 职场文书
学校十一活动方案
2014/02/01 职场文书
房地产广告策划方案
2014/05/15 职场文书
公司周年庆活动方案
2014/08/25 职场文书
报表员工作失误检讨书范文
2014/09/19 职场文书
村党组织公开承诺书
2015/04/30 职场文书
辩护意见书
2015/06/04 职场文书
python如何读取.mtx文件
2021/04/22 Python
OpenStack虚拟机快照和增量备份实现方法
2022/04/04 Servers
JS class语法糖的深入剖析
2022/07/07 Javascript