小伙伴们早上好,今天继续进行共读《科研论文配图绘制指南--基于Python》航海之旅咯~
Task02:2.1 Matplotlib绘图包介绍,掌握matplotlib中基本的图形元素名称,图层顺序和坐标系。多子图绘制方法和常见绘图函数。(页码:18~31)
学习天数:3天
打卡截止时间: 08月23日 03:00
【再次提醒】如果未按时打卡,将要退群处理哦
【课程链接】https://github.com/datawhalechina/paper-chart-tutorial
【学习者手册】
https://mp.weixin.qq.com/s/wXSCQ9fcit7gL0fwAwbtCQ
【小程序使用手册】
https://mp.weixin.qq.com/s/iPmzb72Yk0mhIA2NYezXDg
【船长手册】
https://datawhale.feishu.cn/docs/doccn0YOPvNhGt54Tb2JjxLhDmc#PFdbLL
可以参考的别人的笔记: https://zhuanlan.zhihu.com/p/651237706
2.1.1. 图形元素
- 主要元素: figure 画布, axes 坐标图形, axis 轴, artist 艺术对象
- 坐标图形中: title 图名, tick 刻度, tick label 刻度标签, axis label 轴标签, spine 轴脊, legend 图例, grid 网格, line 线, marker 数据标记
- 元素分类: primitives 基础类 & containers 容器类
- primitives: point, line, grid, title, legend
- containers:
- figure
- 本身可以进行图形绘制, 同时能够被划分为多个子区域绘制子图
- 可以设置图片属性, 如大小 figsize 与分辨率 dpi
- axes
- matplotlib绘图的核心, 绘图的展示区域
- 包含组成图的众多艺术对象 artists
- 一个子图区域由上下左右四个轴脊和其他子图元素组成
- axis
- 数据轴对象, 每个轴对象都包括 位置对象 locator 和 格式对象 formatter, 控制坐标轴刻度的位置和格式
- ticks
- 刻度对象
- 每个坐标图形都包括 横轴对象 X axis 和 纵轴对象 Y axis
- 包括 主刻度 major tick, 次刻度 minor tick, 主刻度标签 major tick label, 次刻度标签 minor tick label
- artists
- primitives和containers均被称为artists
- artists通常与axes绑定, 并不能与多个axes共享, 也不能在figure内移动
2.1.2. 图层顺序
- 通过设置绘图函数中的zorder参数设定不同的图层
- z-order大为靠上侧
- matplotlib Zorder docs
艺术对象 | z-order |
---|---|
Images(AxesImage, FigureImage, BboxImage) | 0 |
Patch / PatchCollection | 1 |
Line2D / LineCollection | 2 |
Text | 3 |
Inset axes / Legend | 4 |
"""an example for Zorder"""
r = numpy.linspace(0.3, 1, 30)
theta = numpy.linspace(0, 4*numpy.pi, 30)
x = r * numpy.sin(theta)
y = r * numpy.cos(theta)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(6, 3.2))
ax1.plot(x, y, 'C3', lw=3)
ax1.scatter(x, y, s=120)
ax1.set_title('Lines on top of dots')
ax2.plot(x, y, 'C3', lw=3)
ax2.scatter(x, y, s=120, zorder=2.5) # move dots on top of line
ax2.set_title('Dots on top of lines')
plt.tight_layout()
plt.show()
2.1.3. 轴比例和刻度
轴比例 axis scale, 刻度位置 tick locator, 刻度格式 tick formatter
- 轴比例
-linear
,log
,symlog
,logit
- 刻度位置和刻度格式
-FixedLocator
,MultipleLocator
,MaxNLocator
,AutoLocator
,LogLocator
,IndexLocator
,LinearLocator
,NullLocator
"""show linear, log, logit, symlog
use numpy and matplotlib
"""
x = numpy.arange(1000)
y = numpy.linspace(0, 1, 1000)
fig, axes = plt.subplots(2,2,figsize=(8,6))
axes = axes.flatten()
scale = ['linear', 'log', 'logit', 'symlog']
for ax, s in zip(axes, scale[:3]):
ax.plot(x, y)
ax.set_title(s)
ax.set_yscale(s)
ax.grid()
# ax[0].set_yticks([0, 0.5, 1])
# ax[0].set_yticklabels([0, 0.5, 1]
ax = axes[3]
s = scale[3] # symlog
ax.plot(x, y-0.5)
ax.set_title(s)
ax.set_yscale(s, linthreshy=0.0001)
ax.grid()
fig.tight_layout()
plt.show()
2.1.4. 坐标轴
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
# Setup a plot such that only the bottom spine is shown
def setup(ax):
ax.spines['right'].set_color('none')
ax.spines['left'].set_color('none')
ax.yaxis.set_major_locator(ticker.NullLocator())
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.tick_params(which='major', width=1.00)
ax.tick_params(which='major', length=5)
ax.tick_params(which='minor', width=0.75)
ax.tick_params(which='minor', length=2.5)
ax.set_xlim(0, 5)
ax.set_ylim(0, 1)
ax.patch.set_alpha(0.0)
plt.figure(figsize=(8, 6))
n = 8
# Null Locator
ax = plt.subplot(n, 1, 1)
setup(ax)
ax.xaxis.set_major_locator(ticker.NullLocator())
ax.xaxis.set_minor_locator(ticker.NullLocator())
ax.text(0.0, 0.1, "NullLocator()", fontsize=14, transform=ax.transAxes)
# Multiple Locator
ax = plt.subplot(n, 1, 2)
setup(ax)
ax.xaxis.set_major_locator(ticker.MultipleLocator(0.5))
ax.xaxis.set_minor_locator(ticker.MultipleLocator(0.1))
ax.text(0.0, 0.1, "MultipleLocator(0.5)", fontsize=14,
transform=ax.transAxes)
# Fixed Locator
ax = plt.subplot(n, 1, 3)
setup(ax)
majors = [0, 1, 5]
ax.xaxis.set_major_locator(ticker.FixedLocator(majors))
minors = np.linspace(0, 1, 11)[1:-1]
ax.xaxis.set_minor_locator(ticker.FixedLocator(minors))
ax.text(0.0, 0.1, "FixedLocator([0, 1, 5])", fontsize=14,
transform=ax.transAxes)
# Linear Locator
ax = plt.subplot(n, 1, 4)
setup(ax)
ax.xaxis.set_major_locator(ticker.LinearLocator(3))
ax.xaxis.set_minor_locator(ticker.LinearLocator(31))
ax.text(0.0, 0.1, "LinearLocator(numticks=3)",
fontsize=14, transform=ax.transAxes)
# Index Locator
ax = plt.subplot(n, 1, 5)
setup(ax)
ax.plot(range(0, 5), [0]*5, color='white')
ax.xaxis.set_major_locator(ticker.IndexLocator(base=.5, offset=.25))
ax.text(0.0, 0.1, "IndexLocator(base=0.5, offset=0.25)",
fontsize=14, transform=ax.transAxes)
# Auto Locator
ax = plt.subplot(n, 1, 6)
setup(ax)
ax.xaxis.set_major_locator(ticker.AutoLocator())
ax.xaxis.set_minor_locator(ticker.AutoMinorLocator())
ax.text(0.0, 0.1, "AutoLocator()", fontsize=14, transform=ax.transAxes)
# MaxN Locator
ax = plt.subplot(n, 1, 7)
setup(ax)
ax.xaxis.set_major_locator(ticker.MaxNLocator(4))
ax.xaxis.set_minor_locator(ticker.MaxNLocator(40))
ax.text(0.0, 0.1, "MaxNLocator(n=4)", fontsize=14, transform=ax.transAxes)
# Log Locator
ax = plt.subplot(n, 1, 8)
setup(ax)
ax.set_xlim(10**3, 10**10)
ax.set_xscale('log')
ax.xaxis.set_major_locator(ticker.LogLocator(base=10.0, numticks=15))
ax.text(0.0, 0.1, "LogLocator(base=10, numticks=15)",
fontsize=15, transform=ax.transAxes)
# Push the top of the top axes outside the figure because we only show the
# bottom spine.
plt.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=1.05)
plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-koQSZc4u-1692666874432)(task2_ticks.png)]
2.1.4. 坐标系
- 直角坐标系
- 极坐标系
- 地理坐标系
- 仅有Aitoff投影, Hammer投影, Lambert投影和Mollweid投影
- matplotlib不适合绘制地理图标, cartopy和proplot更适合
2.1.5. 多子图绘制
subplot()
函数
-subplot(nrows, ncols, index, **kwargs)
- e.g.plt.subplot(2, 2, 1)
, 2行2列第1个子图add_subplot()
函数
-add_subplot(nrows, ncols, index, **kwargs)
- e.g.fig.add_subplot(2, 2, 1)
, 2行2列第1个子图subplots()
函数
-subplots(nrows=1, ncols=1, sharex=False, sharey=False, squeeze=True, subplot_kw=None, gridspec_kw=None, **fig_kw)
axes()
函数
- 为当前figure添加axes对象, 使其成为当前axes对象
- 参数为rect=[left, bottom, width, height]
- 可以用于添加colorbar的ax
- e.g.fig.axes([0.1, 0.1, 0.8, 0.8])
subplot2grid()
函数
-subplot2grid(shape, loc, rowspan=1, colspan=1, fig=None, **kwargs)
- e.g.plt.subplot2grid((3, 3), (1, 0), colspan=2)
, 3行3列, 从(1, 0)开始, 跨2列gridspec.GridSpec()
-gridspec.GridSpec(nrows, ncols, figure=None, left=None, bottom=None, right=None, top=None, wspace=None, hspace=None, width_ratios=None, height_ratios=None)
subplot_mosaic()
- `subplot_mosaic(layout, *, filled=False, **kwargs)
"""subplot()"""
[plt.subplot(i) for i in [212, 221, 222]]
plt.suptitle('plt.subplot()')
plt.tight_layout()
plt.show()
"""add_subplot()"""
fig = plt.figure()
[fig.add_subplot(i) for i in [212, 221, 222]]
fig.suptitle('fig.add_subplot()')
plt.tight_layout()
plt.show()
"""subplots()"""
fig, axes = plt.subplots(2, 3, sharex=True, sharey=True)
fig.suptitle('plt.subplots()')
fig.tight_layout()
plt.show()
"""axes()"""
plt.subplot(211)
plt.imshow(numpy.random.random((100, 100)))
plt.subplot(212)
plt.imshow(numpy.random.random((100, 100)))
plt.subplots_adjust(bottom=0.1, right=0.8, top=0.9)
cax = plt.axes([0.85, 0.1, 0.075, 0.8])
plt.colorbar(cax=cax)
plt.show()
"""subplot2grid()"""
fig = plt.figure()
ax1 = plt.subplot2grid((3,3), (0,0), colspan=3)
ax1.text(0.5, 0.5, "shape=(3,3), loc=(0,0), colspan=3", ha="center", va="center")
ax2 = plt.subplot2grid((3,3), (1,0), colspan=2)
ax3 = plt.subplot2grid((3,3), (1,2), rowspan=2)
ax3.text(0.5, 0.5, "shape=(3,3), loc=(1,2), \nrowspan=2", ha="center", va="center", rotation=90)
ax4 = plt.subplot2grid((3,3), (2,0))
ax5 = plt.subplot2grid((3,3), (2,1))
plt.suptitle("subplot2grid((3,3), ...)")
plt.tight_layout()
plt.show()
"""gridspec.GridSpec()"""
import matplotlib.gridspec as gridspec
fig = plt.figure(constrained_layout=True)
gspec = gridspec.GridSpec(ncols=3, nrows=3, figure=fig)
ax1 = fig.add_subplot(gspec[0, :])
ax1.text(0.5, 0.5, "gspec[0, 0:3]", ha="center", va="center")
ax2 = fig.add_subplot(gspec[1, :2])
ax3 = fig.add_subplot(gspec[1:, 2])
ax3.text(0.5, 0.5, "gspec[1:, 2]", ha="center", va="center", rotation=90)
ax4 = fig.add_subplot(gspec[2, 0])
ax5 = fig.add_subplot(gspec[-1, -2])
# plt.tight_layout() # constrained_layout=True
plt.suptitle("gridspec.GridSpec(ncols=3, nrows=3)")
plt.show()
"""subplot_mosaic()"""
fig, axes = plt.subplot_mosaic(
### example
# [["A panel", "A panel", "A panel", ],
# ["B panel", "B panel", "edge", ],
# ["C pic", ".", "edge", ]],
### or
"""
AAA
BBC
D.C
""",
### or
# "AAA\nBBC\nD.C",
)
plt.suptitle("gridspec.GridSpec(ncols=3, nrows=3)")
plt.show()
2.1.6. 常见图类型
- kwargs should be further verified
绘图函数 | 图类型 | 核心参数 |
---|---|---|
plot | 线图, 点图, 带连接线的点图 | x, y, color, fmt, linestyle, linewidth, marker, markeredgecolor, markeredgewidth, markerfacecolor, markerfacecoloralt, markersize, label, alpha |
scatter | 散点图 | x, y, s, c, marker, linewidths, edgecolors |
bar / barh | 条形图 | x/y, height, width, color, edgecolor, linewidth, xerr, yerr, error_kw |
axhline / axvline | 水平 / 垂直的直线 | y, xmin, xmax, (x, ymin, ymax), color, linestyle, linewidth, label |
axhspan / axvspan | 水平 / 垂直的矩形块 | ymin, ymax, (xmin, xmax), alpha, facecolor, edgecolor, label, linestyle, linewidth |
text | 在指定位置添加文本 | x, y, s, fontdict, color, bbox, ha, va, wrap, rotation, rotation_mode |
fill_between | 在两条水平曲线之间填充 | x, y1, y2, where, facecolor, edgecolor, label |
pie | 饼图 | x, labels, colors, shadow, startangle |
contour | 等高线图 | X, Y, Z, levels, colors, cmap, linewidths, linestyles, alpha, antialiased, data |
step | 阶梯图 | x, y, fmt, where, label |
stem | 茎叶图 | x, y, linefmt, markerfmt, basefmt, bottom, label, use_line_collection |
boxplot | 箱线图 | x, notch, sym, vert, whis, positions, widths, patch_artist, bootstrap |
errorbar | 误差线图 | x, y, xerr, yerr, fmt, ecolor, capsize |
hist | 直方图 | x, bins, normed, color, alpha |
violinplot | 小提琴图 | x, vert, whis, positions, widths, patch_artist, bootstrap |
imshow | 热力图 | X, cmap, norm, aspect, interpolation, alpha, vmin, vmax, origin, extent, filternorm, filterrad, resample, url, data |
pcolor | 伪彩图 | X, cmap, norm, vmin, vmax, alpha, edgecolors, data |
pcolormesh | 伪彩图 | X, cmap, norm, vmin, vmax, alpha, edgecolors, data |
contourf | 填充等高线图 | X, Y, Z, levels, colors, cmap, norm, alpha, antialiased, data |
2.1.7. 保存结果
savefig()
必须出现在show()
函数之前, 避免保存空白- kw
bbox_inches='tight'
去除空白边缘
fig.savefig('figpath.svg', dpi=400, bbox_inches='tight')
fig.savefig('figpath.png', dpi=400, bbox_inches='tight')
plt.show()
各种画图函数
"""show examples to above plot functions
generate data on the run for plotting"""
import matplotlib.pyplot as plt
from matplotlib.pyplot import Axes
import numpy
from typing import List
fig, axes = plt.subplots(4,5, figsize=(25,20), dpi=400)
axes:List[Axes] = axes.flatten()
"""plot"""
idx = 0
x = numpy.arange(0, 10, 0.1)
axes[idx].plot(x, numpy.sin(x))
axes[idx].set_title("plot")
"""scatter"""
idx += 1
axes[idx].scatter(numpy.random.rand(100), numpy.random.rand(100))
axes[idx].set_title("scatter")
"""bar"""
idx += 1
axes[idx].bar(numpy.arange(0, 10, 1), numpy.random.rand(10))
axes[idx].set_title("bar")
"""barh"""
idx += 1
axes[idx].barh(numpy.arange(0, 10, 1), numpy.random.rand(10))
axes[idx].set_title("barh")
"""axhline/axvline"""
idx += 1
axes[idx].axhline(y=0.5, xmin=0.25, xmax=0.75, color='r', linestyle='--')
axes[idx].axvline(x=0.5, ymin=0.25, ymax=0.75, color='r', linestyle='--')
axes[idx].set_title('axhline')
"""axhspan/axvspan"""
idx += 1
axes[idx].axhspan(ymin=0.25, ymax=0.75, xmin=0.25, xmax=0.75, alpha=0.5)
axes[idx].axvspan(xmin=0.25, xmax=0.75, ymin=0.25, ymax=0.75, color='r', alpha=0.5)
axes[idx].set_title('axhspan')
"""text"""
idx += 1
axes[idx].text(0.5, 0.5, 'text', fontsize=20, ha='center', va='center')
axes[idx].set_title('text')
"""fill_between"""
idx += 1
axes[idx].fill_between(x, numpy.sin(x), numpy.cos(x), color='r', alpha=0.5)
axes[idx].set_title('fill_between')
"""pie"""
idx += 1
axes[idx].pie(numpy.random.rand(10), labels=numpy.arange(0, 10, 1))
axes[idx].set_title('pie')
"""contour"""
idx += 1
X, Y = numpy.meshgrid(numpy.arange(-10, 10, 0.1), numpy.arange(-10, 10, 0.1))
Z = numpy.sqrt(X**2 + Y**2)
axes[idx].contour(X, Y, Z)
axes[idx].set_title('contour')
"""step"""
idx += 1
axes[idx].step(numpy.arange(0, 10, 1), numpy.random.rand(10))
axes[idx].set_title('step')
"""stem"""
idx += 1
axes[idx].stem(numpy.arange(0, 10, 1), numpy.random.rand(10))
axes[idx].set_title('stem')
"""boxplot"""
idx += 1
axes[idx].boxplot(numpy.random.rand(100))
axes[idx].set_title('boxplot')
"""errorbar"""
idx += 1
axes[idx].errorbar(numpy.arange(0, 10, 1), numpy.random.rand(10), yerr=numpy.random.rand(10))
axes[idx].set_title('errorbar')
"""hist"""
idx += 1
axes[idx].hist(numpy.random.rand(100))
axes[idx].set_title('hist')
"""violinplot"""
idx += 1
axes[idx].violinplot(numpy.random.rand(100))
axes[idx].set_title('violinplot')
"""imshow"""
idx += 1
axes[idx].imshow(numpy.random.rand(10, 10))
axes[idx].set_title('imshow')
"""pcolor, slower than pcolormesh"""
idx += 1
X, Y = numpy.meshgrid(numpy.arange(-10, 10, 1), numpy.arange(-10, 10, 1))
Z = numpy.sqrt(X**2 + Y**2)
axes[idx].pcolor(X, Y, Z, shading='auto')
axes[idx].set_title('pcolor')
"""pcolormesh, faster than pcolor"""
idx += 1
X, Y = numpy.meshgrid(numpy.arange(-10, 10, 1), numpy.arange(-10, 10, 1))
Z = numpy.sqrt(X**2 + Y**2)
axes[idx].pcolormesh(X, Y, Z, shading='auto')
axes[idx].set_title('pcolormesh')
"""contourf"""
idx += 1
X, Y = numpy.meshgrid(numpy.arange(-10, 10, 1), numpy.arange(-10, 10, 1))
Z = numpy.sqrt(X**2 + Y**2)
axes[idx].contourf(X, Y, Z)
axes[idx].set_title('contourf')
fig.suptitle('examples of matplotlib.pyplot', fontsize=30)
fig.tight_layout()
fig.savefig('task2/task2_examples.png')
plt.show()
![[task2_different_plots.png|800]]