Python_Packages_user ——Matplotlib
本文介绍了Python数据可视化库Matplotlib的常用功能与技巧。重点内容包括:1)网格绘制(plt.grid)的参数设置;2)面向对象编程方式(Figure和Axes对象)的优势;3)子图布局方法(plt.subplot/subplot2grid)及其constrained_layout参数;4)图片保存技巧(plt.savefig)与路径管理;5)图例设置(plt.legend)与坐标轴
本系列文章将记录一些常用的Python第三方库的使用,例如matplotlib,numpy,pandas等来协同完成关于数学建模算法,机器学习等项目的实行。
Note:本人尽量整理相关函数,但是整理的原则是我在使用的过程中感到比较陌生的函数(本人有一定的MATLAB基础)
一. Matplotlib ——可视化常用的第三方库
1. def重定义
通常对于库名进行重定义 ,便于引用
import matplotlib.pyplot as plt
2.plt.grid(*arg) :绘制网格函数
具体参数有:visible {bool} 表示是否显示网格,参数值状态有False Ture
alpha{float} 表示网格线的可视化程度,取值 0~1,例如:alpha=0.3,表示网格线30%的可见度
which :网格线有magor 主要的,次要的minor,默认是magor
axis:表示沿着哪一个轴的网格线,default=both(沿着x轴,y轴都有,所以是从横交叉的网格)
linewidth :网格线的宽度
linestyle :网格线形式
其中最重要的参数是visible 和 alpha
Demo:
plt.grid(
visible=True, # 是否显示网格
which='major', # 网格类型:'major'(主网格)、'minor'(次网格)、'both'
axis='both', # 坐标轴方向:'both'、'x'、'y'
alpha=0.3, # 透明度(0.0-1.0)
color='gray', # 网格线颜色
linestyle='--', # 线型:'-'实线、'--'虚线、'-.'点划线、':'点线
linewidth=0.5 # 线宽
)
3.plt.figure(*arg)函数的注意事项
通常plt.figure(10,5)用于桌面上的照片显示,最常用。
参数1:figure_width,单位是inch(英寸),参数二:figure_height,单位Inch
4. plt.tight_layout()
为了确保布局更加紧凑美观,最后在plt.show()之前(该函数一定是最后执行的函数),加一个plt.tight.layout()函数,确保布局紧凑。
5.面向对象编程的思路
在matplotlib里边,最常使用的绘图方式是:面向对象编程,即将整个图片Figure和每一个具体的绘图区域axes,视为操作对象,这样子调用具体的函数更加简单,可读性强,而且可以将关于整个图片Figure的一些属性, 比如:bbox(bounding box)图片边框设置,figsize,DPI,figure_path等等属性,和关于每一个具体的绘图区域axes(axis的复数形式,坐标轴)的属性,比如xlabel,xdisk,title,legend,linestyle,linecolor,等等关于图形相关的属性分开,通常我们进行自定义调参的时候,一般是关于axes的参数。
6. plt.subplot(*arg)
明确Figure和Axes两个参数之后,接下来介绍最常用的绘图方式,尤其是一个Figure里边有很多个子图,具体格式如下:
fig axes =plt.subplot(m,n)
当然,subplot函数还有很多参数,比如constrained_layout {bool} 这个参数很重要,中文是“受限布局”,顾名思义,可以对布局进行限制,使其更加规范,防止重叠现象,有点像plt.tight.layout(),但是二者不一样,可以亲自试一下。
具体使用的Demo:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
plt.style.use('seaborn-v0_8-bright')
plt.rcParams['font.sans-serif'] = ['SimHei'] # 只用一种字体
plt.rcParams['axes.unicode_minus'] = False
fig1, axes1 = plt.subplots(2, 2, figsize=(10, 8))
for i in range(2):
for j in range(2):
axes1[i, j].plot(np.random.rand(10))
axes1[i, j].set_title(f'非常长的标题 {i},{j} '*3)
axes1[i, j].set_xlabel('X轴标签')
axes1[i, j].set_ylabel('Y轴标签')
fig1.suptitle('不使用constrained_layout', fontsize=16)
plt.tight_layout()
plt.show()
#
# 使用constrained_layout
fig2, axes2 = plt.subplots(2, 2, figsize=(10, 8),
constrained_layout=True)
for i in range(2):
for j in range(2):
axes2[i, j].plot(np.random.rand(10))
axes2[i, j].set_title(f'非常长的标题 {i},{j} '*3) #字符串乘法
axes2[i, j].set_xlabel('X轴标签')
axes2[i, j].set_ylabel('Y轴标签')
fig2.suptitle('使用constrained_layout', fontsize=16)
plt.tight_layout()
plt.show()
总结:constrained_layut=True时,可以合理规范布局,对于很长的标题或者标签,都不会发生重叠。
7.关于Figure_Save的问题
1.相关函数是:plt.savefig(*arg) 内部参数有很多,但最重要的就是第一个filename{str}参数,其余的都是默认即可,特殊需求可自行查阅文档。
2.当filename只是给figure起一个命名的话,那么会默认保存到当前工作项目目录下,同时可以对保存的格式进行选择,filename.pdf, .png 等等格式
3.若想更换保存路径,也可以自行选择路径,然后赋值给第一个参数即可,save_path常用的设置方法有两种。
第一种:手动搜索目标文件夹的标准硬盘位置 例如:D:\PythonProjects\AnacondaProject1\Matplotlib_Projects\Result,讲标准的硬盘系统路径赋值给save_path,然后再自行加上照片名称和格式即可一同传送给savefig函数。
第二种:使用os第三方库里边的os.mkdir(str),os.path_join(str)等函数,快速组装起保存的路径,本人整理了一个函数模块,便于进行自定义保存照片。
import os
def save_figure_customed(filename,save_directory='Result\Figures'):
if not os.path.exists(save_directory):
os.makedirs(save_directory)
save_path=os.path.join(save_directory,filename)
plt.savefig(save_path,bbox_inches='tight)
Note:Os第三方库是专门用来和电脑操作系统交互使用的库,可以用来快速获取文件路径,建立文件夹等操作,需要提前引用进项目当中。
savefig(*arg)函数中的参数bbox_inches='tight',主要是用来保存Figure时裁剪边框的空白,照片会显得更加紧凑。
8. 注意,虽然说最常用的绘图方法是面向对象绘图,但是最后的显示代码,仍然要是
plt.tight.layout()
plt.show()
若仍然适用fig对象操作,照片会闪一下,然后代码执行结束,无法直接观看FIgure。
9.plt.legend(*arg)
图例函数:plt.legend(*arg),注意参数loc(即 location), loc='upper right'表示将图例添加到右上角,然后若使用plt为对象时,loc=0表示自动寻找最好的位置,但是若使用axes为对象时,没有这个选项,只可以自动添加字符串位置。
10.Axes对象
关于axes对象的绘图属性,提供一个可以实践的Demo:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib
import os
matplotlib.use('TkAgg')
plt.style.use('seaborn-v0_8-bright')
plt.rcParams['font.sans-serif'] = ['SimHei'] # 只用一种字体
plt.rcParams['axes.unicode_minus'] = False
# 创建图形和坐标轴
fig, ax = plt.subplots(figsize=(10,5))
# #
# # # 1. 绘制不同类型的数据
x = np.linspace(0, 10, 100)
ax.plot(x, np.sin(x), 'b-', label='sin(x)', linewidth=2)
ax.scatter(x[::10], np.cos(x[::10]), c='red', s=50, label='cos(x)采样点')
ax.fill_between(x, np.sin(x), 0, where=(np.sin(x)>0),
color='green', alpha=0.3, label='正半轴区域')
plt.legend(loc='upper right') #参数loc:location位置参数,右上角
plt.legend(loc=0)
plt.show()
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
# 两个子图绘制相同标签的曲线
line1, = ax1.plot(x, np.sin(x), label='sin(x)')
line2, = ax1.plot(x, np.cos(x), label='cos(x)')
ax2.plot(x, -np.sin(x), label='sin(x)')
ax2.plot(x, -np.cos(x), label='cos(x)')
# 创建统一图例
fig.legend([line1, line2], ['正弦函数', '余弦函数'],
loc='upper right', ncol=2)
plt.tight_layout()
plt.show()
# 2. 坐标轴控制方法
print("=== Axes对象方法 ===")
# 设置标签
ax.set_xlabel('X轴标签', fontsize=12)
ax.set_ylabel('Y轴标签', fontsize=12)
ax.set_title('坐标轴方法示例', fontsize=14, fontweight='bold')
# 设置坐标轴范围
ax.set_xlim(0, 10)
ax.set_ylim(-1.5, 1.5)
# 设置刻度
ax.set_xticks(np.arange(0, 11, 2))
ax.set_yticks(np.arange(-1.5, 2, 0.5))
ax.tick_params(axis='both', labelsize=10)
# 添加网格
ax.grid(True, which='both', linestyle='--', alpha=0.5)
# 添加图例
ax.legend(loc='upper right', fontsize=10, framealpha=0.9)
# 3. 添加各种图形元素
# 水平线和垂直线
ax.axhline(y=0, color='black', linewidth=0.8, linestyle='-')
ax.axvline(x=5, color='red', linewidth=1, linestyle='--', alpha=0.7)
# 填充区域
ax.axvspan(2, 4, alpha=0.2, color='yellow')
ax.axhspan(-0.5, 0.5, alpha=0.2, color='blue')
# 箭头标注
ax.annotate('最大值点', xy=(np.pi/2, 1), xytext=(4, 1.2),
arrowprops=dict(arrowstyle='->', color='green'),
fontsize=10, ha='center')
# 4. 获取坐标轴属性
print(f"X轴范围: {ax.get_xlim()}")
print(f"Y轴范围: {ax.get_ylim()}")
print(f"X轴标签: {ax.get_xlabel()}")
print(f"Y轴标签: {ax.get_ylabel()}")
print(f"标题: {ax.get_title()}")
plt.tight_layout()
plt.show()
10.plt.suptitle(*arg)
plt.suptitle(*arg),最后对于整个figure的一个属性——super title总标题,需要注意的参数是y,
y=1.02,表示距离图形axes的顶部高出2%,y=1,则与图形顶部距离最近,默认是1,y太大,会导致在导出的时候,主标题被“截断”。
11.plt.subplot2grid(*arg)
复杂布局常用函数plt.subplot2grid(*arg),和plt.subplots(*arg),类似,但是更加灵活
plt.subplot2grid(*arg)的参数有:
1.(m,n),表示将整个Figure分成m行n列
2. (m_start,n_start)表示绘制的子图起始的行列数,注意是从0开始的
3. colspan=n,表示span (渲染)n列,4. rowspan=m,表示渲染行,从1开始(因为是数字,不是index表示,所以n就代表n列,m就代表m行,没有所谓的n+1,m+1)
Note:该函数返回值只是一个axes_n参数,没有fig对象,返回的对象是一个不可迭代的对象
Demo:
import matplotlib.pyplot as plt
import numpy as np
import os
import matplotlib.gridspec as gridspec
import matplotlib
matplotlib.use('TkAgg')
plt.style.use('seaborn-v0_8-bright')
plt.rcParams['font.sans-serif'] = ['SimHei'] # 只用一种字体
plt.rcParams['axes.unicode_minus'] = False
# 方法1:使用subplot2grid
fig = plt.figure(figsize=(14, 10))
# 创建2x2的网格,但第一个子图占两列
ax1 = plt.subplot2grid((3, 4), (0, 0), colspan=4, rowspan=2)
ax2 = plt.subplot2grid((3, 4), (2, 0), colspan=1)
ax3 = plt.subplot2grid((3, 4), (2, 1), colspan=1)
ax4 = plt.subplot2grid((3, 4), (2, 2), colspan=1)
ax5 = plt.subplot2grid((3, 4), (2, 3), colspan=1)
# 绘制内容
x = np.linspace(0, 10, 100)
ax1.plot(x, np.sin(x), 'b-', label='主图')
ax1.set_title('主图(占两行四列)')
ax1.legend()
ax1.grid(True)
for i, ax in enumerate([ax2, ax3, ax4, ax5], 1):
ax.plot(x, np.random.randn(100).cumsum())
ax.set_title(f'子图{i}')
ax.grid(True, alpha=0.3)
plt.suptitle('使用subplot2grid的复杂布局', fontsize=16, y=1)
plt.tight_layout()
plt.show()
更多推荐

所有评论(0)