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 文件读写操作实例详解
Mar 12 Python
解读! Python在人工智能中的作用
Nov 14 Python
谈谈python中GUI的选择
Mar 01 Python
实例讲解python中的协程
Oct 08 Python
梅尔倒谱系数(MFCC)实现
Jun 19 Python
python向字符串中添加元素的实例方法
Jun 28 Python
Python中 CSV格式清洗与转换的实例代码
Aug 29 Python
python实现多线程端口扫描
Aug 31 Python
OpenCV+Python3.5 简易手势识别的实现
Dec 21 Python
python cv2图像质量压缩的算法示例
Jun 04 Python
python中pycryto实现数据加密
Apr 29 Python
Python 中面向接口编程
May 20 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 获取本地IP代码
2013/06/23 PHP
PHP parse_ini_file函数的应用与扩展操作示例
2019/01/07 PHP
Google AJAX 搜索 API实现代码
2010/11/17 Javascript
解析JavaScript中的标签语句
2013/06/19 Javascript
jquery数据验证插件(自制,简单,练手)实例代码
2013/10/24 Javascript
table行随鼠标移动变色示例
2014/05/07 Javascript
jQuery的css() 方法使用指南
2015/05/03 Javascript
javascript获取select值的方法分析
2015/07/02 Javascript
Jquery效果大全之制作电脑健康体检得分特效附源码下载
2015/11/02 Javascript
JQuery Ajax WebService传递参数的简单实例
2016/11/02 Javascript
VueJs 搭建Axios接口请求工具
2017/11/20 Javascript
微信小程序实现渐入渐出动画效果
2019/06/13 Javascript
详解JavaScript 浮点数运算的精度问题
2019/07/23 Javascript
JsonServer安装及启动过程图解
2020/02/28 Javascript
解决vue net :ERR_CONNECTION_REFUSED报错问题
2020/08/13 Javascript
详解阿里Node.js技术文档之process模块学习指南
2021/01/04 Javascript
[03:12]完美世界DOTA2联赛PWL DAY6集锦
2020/11/05 DOTA
Python Mysql数据库操作 Perl操作Mysql数据库
2009/01/12 Python
Python实现快速排序和插入排序算法及自定义排序的示例
2016/02/16 Python
python实现基于信息增益的决策树归纳
2018/12/18 Python
python实现抠图给证件照换背景源码
2019/08/20 Python
Python 基于jwt实现认证机制流程解析
2020/06/22 Python
在Tensorflow中实现leakyRelu操作详解(高效)
2020/06/30 Python
快速解决pymongo操作mongodb的时区问题
2020/12/05 Python
Django扫码抽奖平台的配置过程详解
2021/01/14 Python
Python实现微信表情包炸群功能
2021/01/28 Python
基于tensorflow __init__、build 和call的使用小结
2021/02/26 Python
新加坡时尚网上购物:Zalora新加坡
2016/07/26 全球购物
柒牌官方商城:中国男装优秀品牌
2017/06/30 全球购物
Vans奥地利官方网站:美国原创极限运动潮牌
2018/09/30 全球购物
北京-环亚运商测试题.net程序员初步测试题
2013/05/28 面试题
某同学的自我鉴定范文
2013/12/26 职场文书
中学生国旗下讲话稿
2014/04/26 职场文书
中国汉字听写大会观后感
2015/06/02 职场文书
西游记读书笔记
2015/06/25 职场文书
大学生暑期实践报告
2015/07/13 职场文书