赞
踩
根据《科研论文配图绘制指南——基于Python》第二章Matplotlib部分,对章节重点进行归纳总结,主要介绍了运用Matplotlib库绘图中图形元素、图层顺序、轴比例刻度、坐标系概念以及多子图绘制方法、库中常见的图类型与图片保存方法
如果用户想要寻找一款开源且功能强大的绘图工具,那么可以尝试使用Python。Python 作为一门开源编程语言,其易学性和可扩展性使它在可视化绘图领域有不错的表现。在学术图表的绘制方面,Python 有多个第三方库,包括基础绘图库 Matplotlib、统计分析可视化库 Seaborn、科学绘图库 ProPlot 和科学绘图主题库 SciencePlots 等。
本篇笔记重点讲述Matplotlib
Matplotlib是 Python 中较为常用和知名的可视化绘图工具。它提供了几十种绘图函数。用户可以根据需求定制可视化视觉样式和排版布局。
利用 Matplotlib 绘制图形的主要图形元素包括画布(figure)、坐标图形(axes)、轴(axis)和艺术对象(aritist)。
其中坐标图形中包括大部分绘图所需的图层属性,如图名(title)、刻度(tick)、刻度标签(tick label)、轴标签(axis label)、轴脊(spine)、图例(legend)、网格(grid)、线(line)和数据标记(marker)等。
Matplotlib包含基础类(primitive)元素和容器类(container)元素。
基础类元素和容器类元素统称为 Matplotlib 库中的艺术对象 (artist)。在通常情况下,艺术对象与坐标图形 (axes) 对象绑定且不能被其他或多个坐
标图形对象共享,也不能从一个坐标图形区域移动到另一个坐标图形区域。
Matplotlib 采用的是面向对象的绘图方式。在同一个坐标图形中绘制不同的数据图层时,
Matplotlib 可通过设置每个绘图函数中的 zorder 参数来设定不同的图层。
不同的艺术对象在坐标图形中的默认图层顺序如下表:
艺术对象 | z-order |
---|---|
Images(AxesImage, FigureImage, BboxImage) | 0 |
Patch / PatchCollection | 1 |
Line2D / LineCollection | 2 |
Text | 3 |
Inset axes & Legend | 4 |
坐标轴刻度的合理设置将提升图的可读性,方便读者理解所呈现的数据。Matplotlib 中的每个坐标图形对象至少包含两个轴对象,它们分别用来表示 X 轴和 Y 轴。轴对象还可以控制轴比例(axis scale)、刻度位置(tick locator)和刻度格式(tick formatter)
1.轴比例
轴比例规定了数值与给定轴之间的映射方式,即数值在轴上以何种方式进行缩放。Matplotlib 中的默认轴比例方式为线性(linear)方式,其他诸如 log、logit、symlog 和自定义函数比例(function scale)方式也是常用的轴比例方式。需要注意的是,当我们采用不同的轴比例方式时,刻度位置和刻度格式也会相应产生变动。
2.刻度位置和刻度格式
刻度位置和刻度格式分别规定了每个轴对象上刻度的位置与格式。
常见的坐标系有直角坐标系(rectangular coordinate system)、极坐标系(polar coordinate system)和地理坐标系(geographic coordinate system),其中直角坐标系和地理坐标系在科研论文绘图中出现的频率较高。
极坐标系往往体现数据的周期性,即它可以更好地展示数据的周期性变化,这就要求数据较为完整且有明显的周期性特征。而对于常见的科研论文配图,由于数据本身的问题,因此导致很少使用极坐标系绘制它们(地理空间类图表除外)。
特别是在对变量连续时间变化趋势分析的情况下,极坐标系对数据的展示效果不如直角坐标系。
Matplotlib 地理坐标系中的地理投影方式较少,仅有 Aitoff 投影、Hammer 投影、Lambert投影和 Mollweide 投影 4 种。Matplotlib 不适合绘制地理图表,我们可使用 Python 的第三方库(如 cartopy、ProPlot 等库)绘制地理图表。
如果我们想要在一个图形中绘制多个子图,则需要使用 Matplotlib 中的多子图绘制功能。Matplotlib 中提供了多个用来绘制多子图的函数。
Matplotlib 提供的 subplot() 函数可以对当前画布对象添加单个子图,且每次添加子图都会规定其位置顺序。
import matplotlib.pyplot as plt
ax1 = plt.subplot(212)
ax2 = plt.subplot(221)
ax3 = plt.subplot(222)
括号中整数表示子图的网格位置,例如:221表示在2x2的网格中,第1个位置。也就是说,它将创建一个2x2的网格,并在第3个位置上绘制一个子图。
注意:在此处,网格的编号是从1开始的,而不是从0开始。所以,223实际上是指的第3个子图。
绘制结果如下图所示。
Matplotlib 中的 add_subplot() 函数的使用方法和 subplot() 函数类似,不同之处是,add_subplot() 函数需先产生 figure 对象,然后在该对象的基础上依次添加子图
代码示例如下
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = fig.add_subplot(212)
ax2 = fig.add_subplot(221)
ax3 = fig.add_subplot(222)
Matplotlib 提供的 subplots() 函数是常见的用于绘制子图的函数。该函数的语法格式如下:
subplots(nrows, ncols, sharex, sharey)
该函数的第 1 个参数 nrows 表示绘制子图的行数,第 2 个参数 ncols 表示绘制子图的列数,行数与列数的乘积即绘制的总子图数,第 3 个参数 sharex 可以用来设定是否共享 X 轴,第 4个参数 sharey 可以用来设定是否共享 Y 轴。该函数会返回一个坐标数组对象,该对象用于每个子图的单独绘制。
代码如下
fig, axs = plt.subplots(2, 3, sharex=True, sharey=True)
axs[0,0].text(0.2, 0.5, "subplots(0,0)") #在(0,0)的子图上添加文本,后续代码同理
axs[0,1].text(0.2, 0.5, "subplots(0,1)")
axs[0,2].text(0.2, 0.5, "subplots(0,2)")
axs[1,0].text(0.2, 0.5, "subplots(1,0)")
axs[1,1].text(0.2, 0.5, "subplots(1,1)")
axs[1,2].text(0.2, 0.5, "subplots(1,2)")
代码绘制图像如下图:
Matplotlib 中的 axes() 函数的主要功能是为当前画布 (figure) 对象添加坐标图形 (axes) 对象,使其成为当前的坐标图形(axes)对象。
此外,还需要提供 rect 参数(一个四元组:left、 bottom、width、height)。
axes() 函数常见用法包括对当前画布 (figure) 对象中的坐标图形 (axes) 对象添加颜色和大小映射等,或者在已有的坐标图形 (axes) 对象上添加另一个坐标图形 (axes) 对象。
代码如下:
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(19680801)
plt.subplot(211)
plt.imshow(np.random.random((100, 100)))
plt.subplot(212)
plt.imshow(np.random.random((100, 100)))
plt.subplots_adjust(bottom=0.1, right=0.8, top=0.9) #调整子图网格的位置和大小
cax = plt.axes([0.8, 0.1, 0.05, 0.8]) #创建一个颜色条对象,用于显示图像的颜色对应的数值。指定颜色条的位置和大小。
plt.colorbar(cax=cax)
Matplotlib 中的 subplot2grid() 函数可以实现对不规则多子图的绘制,即在当前画布对象上绘制网格(grid),网格可用于在特定位置绘制布局和大小不同的子图对象。subplot2grid() 函数的语法格式如下。
subplot2grid(shape, location, rowspan/colspan)
该函数的第 1 个参数 shape 规定了的网格的行数和列数,第 2 个参数 location 决定了子图在网格内的行号和列号,第 3 个参数为 rowspan 或 colspan,它们分别规定了每个子图向下跨越的行数和向右跨越的列数,也就实现了大小不一的子图的绘制。
示例代码如下:
import matplotlib.pyplot as plt
fig = plt.figure()
ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=3)
ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2)
ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
ax4 = plt.subplot2grid((3, 3), (2, 0))
ax5 = plt.subplot2grid((3, 3), (2, 1))
Matplotlib 中的 gridspec.GridSpec() 函数用于指定放置子图的网格的几何形状。该函数的语法构式如下。
gridspec.GridSpec(nrows, ncols, figure, left, bottom, right, top)
其中,参数 nrows 表示网格中的行数;参数 ncols 表示网格中的列数;left、bottom、right和 top 是可选参数,用于将子图的范围定义为图形宽度或高度的一部分。
在绘制子图时,首先使用 gridspec.GridSpec() 函数中的 nrows 和 ncols 参数分别设定网格中的行数与列数;然后使用 left、bottom、right 和 top 参数设定网格在图形中的具体位置;最后针对 gridspec.GridSpec() 函数的结果,利用 subplot() 函数进行具体子图的选择和定制化操作。
示例代码如下。
import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec fig = plt.figure(constrained_layout=True) gspec = gridspec.GridSpec(ncols=3, nrows=3, figure=fig) ax1=plt.subplot(gspec[0,:]) ax1.text(0.3, 0.5, "gspec[0,:]") ax2=plt.subplot(gspec[1,0:2]) ax2.text(0.3, 0.5, "gspec[1,0:2]") ax3=plt.subplot(gspec[1:,2]) ax3.text(0.3, 0.5, "gspec[1:,2]") ax4=plt.subplot(gspec[2,0]) ax4.text(0.3, 0.5, "gspec[2,0]") ax5=plt.subplot(gspec[-1,-2]) ax5.text(0.3, 0.5, "gspec[-1,-2]")
示意图如下所示:
Matplotlib 中的 subplot_mosaic() 函数的语法格式如下。
subplot_mosaic(mosaic,…)
subplot_mosaic() 函数绘制子图的最大特点是它可利用 mosaic 参数设置特定字符串符号(重复次数、顺序等)来进行子图的视觉布局。
示例代码如下:
def annotate_axes(ax, text, fontsize):
ax.text(0.5, 0.5, text, transform=ax.transAxes,fontsize=fontsize, alpha=0.75, ha="center",va="center", weight="bold")
fig, axd = plt.subplot_mosaic([['upper left', 'right'], ['lower left', 'right']],figsize=(6,3),constrained_layout=True)
for k in axd:
annotate_axes(axd[k], f'axd["{k}"]', fontsize=14)
示意图如下图所示:
注意:Matplotlib 绘制多子图的每一个方法都有它特定的使用环境。本文大多数子图均采用subplots() 函数绘制。子图的数量尽量控制在 4 个以内。如果多于 4 个子图,那么,不仅会增加绘制的代码量(科研论文配图的定制化绘制需求较高),而且可能导致子图的排列和显示出现问题,如字体大小显示错误,以及刻度的长短、粗细与设置不符等。
Matplotlib 可用于绘制常见的图,如误差图、散点图、柱形图、饼图、直方图和箱线图等。绘制每类图的函数都提供了详细的参数,可用于设置图中的颜色、线条宽度、透明度、形状等。想要使用 Matplotlib 绘制高度定制化的图,就必须了解不同绘制函数的参数。
下表列出了Matplotlib 中常见的绘图函数及其核心参数,以及对应的图类型:
绘图函数 | 函数的核心参数 | 图类型 |
---|---|---|
plot() | x、y、color、fmt(数据点 / 线链接样式)、linestyle、linewidth、marker、 markeredgecolor、markeredgewidth、markerfacecolor、markerfacecoloralt、 markersize、label、alpha、zorder | 线图、点图、带连接线 的点图 |
scatter() | x、y、s(大小)、c(颜色)、marker(形状)、 linewidths、edgecolors | 散点图 |
bar()/barh() | x/y、height(柱高)、width(柱宽)、color(填充颜色)、edgecolor(边框颜色)、 linewidth(边框宽度)、xerr(x 误差)、yerr(y 误差)、error_kw(误差参数) | 柱形图/条形图、 堆积柱形图/堆积条形图 |
axhline()/ axvline() | y、xmin、xmax/(x、ymin、ymax)、color、linestyle、linewidth、label、zorder | 垂直于 X/Y 轴的直线 |
axhspan()/ axvspan() | ymin、ymax/(xmin、xmax)、facecolor、edgecolor、label、linestyle、linewidth、 zorder | 垂直于 X/Y 轴的矩形块 |
text() | x、y、s(文本)、fontdict、zorder、 horizontalalignment、verticalalignment | 文本 |
fill_between() | x、y1、y2、where、facecolor、edgecolor、label、zorder | 面积图、填充图 |
pie() | x、labels、colors、shadow(阴影)、startangle(开始角度) | 饼图 |
contour() | X、Y、Z、levels、colors、cmap、vmin、vmax、linewidths(等高线宽度) | 等高线图 |
step() | x、y、fmt(数据点 / 线链接样式)、where、label、zorder | 步阶图 |
stem() | locs、 heads、 linefmt(连接线形状)、 label | 茎叶图 |
boxplot() | x、notch(有无缺口)、widths、meanline(均值线)、labels、zorder | 箱线图 |
errorbar() | x、y、xerr、yerr、fmt(数据点 / 线链接样式)、ecolor(误差棒颜色)、 capsize( 误 差 棒 横 杠 大 小 )、capthick( 误 差 棒 横 杠 粗 细 )、marker、 markeredgecolor、zorder | 误差线 |
hist() | x、bins(箱总数)、range、density(是否频率统计)、color、label、zorder | 直方图 |
violinplot() | dataset、positions(位置)、widths、 showmeans、showextrema、showmedians、zorder | “小提琴”图 |
Matplotlib 绘制的图对象可以保存为多种格式,如 PNG、JPG、TIFF、PDF 和 SVG 等。注意,结果保存函数 savefig() 必须出现在 show() 函数之前,可避免保存结果为空白等问题。另外,在使用 savefig() 的过程中,我们需要设置参数 bbox_inches=‘tight’,去除图表周围的空白部分。
将图对象保存为 PDF 文件和 PNG 文件的示例代码如下:
fig.savefig('结果.pdf',bbox_inches='tight')
fig.savefig('结果.png', bbox_inches='tight',dpi=300)
plt.show()
、JPG、TIFF、PDF 和 SVG 等。注意,结果保存函数 savefig() 必须出现在 show() 函数之前,可避免保存结果为空白等问题。另外,在使用 savefig() 的过程中,我们需要设置参数 bbox_inches=‘tight’,去除图表周围的空白部分。
将图对象保存为 PDF 文件和 PNG 文件的示例代码如下:
fig.savefig('结果.pdf',bbox_inches='tight')
fig.savefig('结果.png', bbox_inches='tight',dpi=300)
plt.show()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。