概述
这篇文章是一些细致化要求,因为论文的图有时候确实需要各种微调= =
- 首先是面向对象的微调,如Figure对象、Axes对象、lines对象、legend对象等
- 然后是matplotlib.style中自带的样式使用
- 接着是通过覆盖Matplotlib配置文件的rcParams设置
- 最后是再说一些图画呈现过程的底层逻辑
第三篇文章是Seaborn的API以及一些例子
一、 基本可操作对象
可操作对象有很多如图figure,坐标系axes,坐标轴axis,网格grid,图例legend,文本text,标注annotation,刻度Ticks等等
下面只介绍基本常用的对象如Figure、Axes、Lines、Legend与Ticks。
1.1 Lines对象
ax.plot(x_data,y_data)
当我们执行上述命令时,实际上是创建了Lines对象,因此可通过下面的参数传值进去,定制化Lines对象的属性,大致参数有:
参数 |
默认值 |
lines.linewidth |
1.5 |
lines.linestyle |
- |
lines.color |
C0 |
lines.marker |
None |
lines.markerfacecolor |
auto |
lines.markeredgecolor |
auto |
lines.markeredgewidth |
1.0 |
lines.markersize |
6 |
lines.dash_joinstyle |
round |
lines.dash_capstyle |
butt |
lines.solid_joinstyle |
round |
lines.solid_capstyle |
projecting |
lines.antialiased |
True |
lines.dashed_pattern |
3.7, 1.6 |
lines.dashdot_pattern |
6.4, 1.6, 1, 1.6 |
lines.dotted_pattern |
1, 1.65 |
lines.scale_dashes |
True |
markers.fillstyle |
full |
import matplotlib.pyplot as plt
import numpy as np
x_data = np.array([1.0, 2.0, 3.0])
y_data = np.array([3.0, 6.0, 9.0])
fig, ax = plt.subplots()
lines_specification = {'linewidth':2.0, 'marker':'o', 'color':'r','markersize':10}
ax.plot(x_data,y_data,**lines_specification)
plt.show()
1.2 Axes对象(***重要)
接下来的对象以此类推,需要明确的是这些对象究竟是在什么时候创建的,然后把其作为参数传入即可,也可在第二章中设定style。具体例子的体会放在第三篇文章。
fig = plt.figure()
fig.subplots_adjust(top=0.8)
ax1 = fig.add_subplot(211)
ax1.set_ylabel('volts')
ax1.set_title('a sine wave')
参数 |
默认值 |
axes.facecolor |
white |
axes.edgecolor |
black |
axes.linewidth |
0.8 |
axes.grid |
False |
axes.grid.axis |
both |
axes.grid.which |
major |
axes.titlesize |
large |
axes.titleweight |
normal |
axes.titlepad |
6.0 |
axes.labelsize |
medium |
axes.labelpad |
4.0 |
axes.labelweight |
normal |
axes.labelcolor |
black |
axes.axisbelow |
line |
axes.formatter.limits : |
-7, 7 |
axes.formatter.use_locale |
False |
axes.formatter.use_mathtext |
False |
axes.formatter.min_exponent |
0 |
axes.formatter.useoffset |
True |
axes.formatter.offset_threshold |
4 |
axes.spines.left |
True |
axes.spines.bottom |
True |
axes.spines.top |
True |
axes.spines.right |
True |
axes.unicode_minus |
True |
axes.prop_cycle |
cycler(‘color’, [‘1f77b4’, ‘ff7f0e’, ‘2ca02c’, ‘d62728’, ‘9467bd’, ‘8c564b’, ‘e377c2’, ‘7f7f7f’, ‘bcbd22’, ‘17becf’]) |
axes.autolimit_mode |
data |
axes.xmargin |
.05 |
axes.ymargin |
.05 |
polaraxes.grid |
True |
axes3d.grid |
True |
1.3 Ticks对象
参数 |
默认值 |
xtick.top |
False |
xtick.bottom |
True |
xtick.labeltop |
False |
xtick.labelbottom |
True |
xtick.major.size |
3.5 |
xtick.minor.size |
2 |
xtick.major.width |
0.8 |
xtick.minor.width |
0.6 |
xtick.major.pad |
3.5 |
xtick.minor.pad |
3.4 |
xtick.color |
black |
xtick.labelsize |
medium |
xtick.direction |
out |
xtick.minor.visible |
False |
xtick.major.top |
True |
xtick.major.bottom |
True |
xtick.minor.top |
True |
xtick.minor.bottom |
True |
xtick.alignment |
center |
1.4 Legend对象
参数 |
默认值 |
legend.loc |
best |
legend.frameon |
True |
legend.framealpha |
0.8 |
legend.facecolor |
inherit |
legend.edgecolor |
0.8 |
legend.fancybox |
True |
legend.shadow |
False |
legend.numpoints |
1 |
legend.scatterpoints |
1 |
legend.markerscale |
1.0 |
legend.fontsize |
medium |
legend.title_fontsize |
None . |
legend.borderpad |
0.4 |
legend.labelspacing |
0.5 |
legend.handlelength |
2.0 |
legend.handleheight |
0.7 |
legend.handletextpad |
0.8 |
legend.borderaxespad |
0.5 |
legend.columnspacing |
2.0 |
1.5 Figure对象
fig = plt.figure(1)
fig , axs = plt.subplots(2,2)
参数 |
默认值 |
figure.titlesize |
large |
figure.titleweight |
normal |
figure.figsize |
6.4, 4.8 |
figure.dpi |
100 |
figure.facecolor |
white |
figure.edgecolor |
white |
figure.frameon |
True |
figure.max_open_warning |
20 |
figure.subplot.left |
0.125 |
figure.subplot.right |
0.9 |
figure.subplot.bottom |
0.11 |
figure.subplot.top |
0.88 |
figure.subplot.wspace |
0.2 |
figure.subplot.hspace |
0.2 |
figure.autolayout |
False |
figure.constrained_layout.use |
False |
figure.constrained_layout.h_pad |
0.04167 |
figure.constrained_layout.w_pad |
0.04167 |
figure.constrained_layout.hspace |
0.02 |
figure.constrained_layout.wspace |
0.02 |
1.6 Savefig对象
plt.savefig('my_fig.jpg')
参数 |
默认值 |
savefig.dpi |
figure |
savefig.facecolor |
white |
savefig.edgecolor |
white |
savefig.format |
png |
savefig.bbox |
standard |
savefig.pad_inches |
0.1 |
savefig.jpeg_quality |
95 |
savefig.directory |
~ |
savefig.transparent |
False |
savefig.orientation |
portrait |
1.7 小总结
这些参数具体可取的值,除了默认值还有哪些,就可以参见官方的API
比如点进去markers,就可以看到marker的所有可能取值:
二、Matplotlib的配置
配置方式有两种:通过style文件与通过rc文件。
- 首先查看Matplotlib的两种配置文件style与rc文件所在路径
import matplotlib as mpl
print(mpl.matplotlib_fname()) # matplotlibrc文件所在路径
print(mpl.get_configdir()) # 自己设计的style文件所放路径
2.1 Style文件
- 首先写一个style文件my_style.mplstyle
axes.titlesize : 24
axes.labelsize : 20
lines.linewidth : 3
lines.markersize : 10
xtick.labelsize : 16
ytick.labelsize : 16
然后将其放在matplotlib_configdir/stylelib/my_style.mplstyle,便可以通过下面方式使用
(matplotlib_configdir由mpl.get_configdir()获得)
print(plt.style.available)
# output
['seaborn-dark', 'dark_background', 'seaborn-pastel', 'seaborn-colorblind', 'tableau-colorblind10', 'seaborn-notebook', 'seaborn-dark-palette', 'grayscale', 'seaborn-poster', 'seaborn', 'bmh', 'seaborn-talk', 'seaborn-ticks', '_classic_test', 'ggplot', 'seaborn-white', 'classic', 'Solarize_Light2', 'seaborn-paper', 'fast', 'fivethirtyeight', 'seaborn-muted', 'seaborn-whitegrid', 'seaborn-darkgrid', 'seaborn-bright', 'seaborn-deep']
plt.style.use('ggplot')
with plt.style.context('dark_background'):
plt.plot(np.sin(np.linspace(0, 2 * np.pi)), 'r-o')
2.2 rc文件
- 通过修改matplotlib的matplotlibrc配置文件保存style
# rcParams通过dict一个个参数进行动态设置
mpl.rcParams['lines.linewidth'] = 2
mpl.rcParams['lines.color'] = 'r'
# rc通过设定对象"lines",传入keyword argument进行多个设置
mpl.rc('lines', linewidth=4, color='g')
可通过浏览一下A sample matplotlibrc file查看大概有哪些对象,哪些参数是可以设置的
三、底层逻辑
3.1 基本定义
- FigureCanvas : Figure对象所占区域的一个Canvas对象
- Renderer : 在Canvas对象上draw的一个Renderer对象
- Artist:使用Renderer对象在Canvas对象上Paint的一个Artist对象
FIgureCanvas与Renderer主要处理不同的UI,如wxPython或者Jupyter Notebook上等一些交互细节,而Artist则是对Figure上要展示的最基本部件,一般情况下只需要理会Artist。
最基本的Artist对象分为两类,一个是graphical objects的Primitives,另一个是容纳多个primitives的Containers,大致有:
- Primitives:Lind2D、Rectangle、Text等Primitives对象
- Containers:Figure、Axes、Axis、Tick等容器对象
所以,创建一个图的整体逻辑是:
创建一个Container对象,如Figure对象,然后调用Container.method来继续创建容器对象如Axes或者基础的部件Primitives如Lines
对比一下这两种写法:
fig1 = plt.figure(1)
ax11 = fig1.add_subplot(1,2,1)
ax12 = fig1.add_subplot(1,2,2)
fig2 = plt.figure(2)
ax21 = fig2.add_axes([0.15, 0.1, 0.7, 0.3])
ax22 = fig2.add_axes([0.25, 0.25, 0.5, 0.5])
plt.show()
因此subplot是一个Axes的特殊情况,在调用figure对象的add_subplot方法来创建一个plot对象(一个规则的Axes对象)或者调用figure对象的add_axes方法来创建一个axes对象,可以设置在Figure中的位置(left, bottom, width, height)。因此之前的ax.plot(x_data, y_data)实际上就是利用axes对象的plot方法创建一个Line2D对象即Primitives
3.2 组织结构
四种容量最大到小的Container Artist对象:
Figure、Axes、Axis、Tick
- Figure :只列四个
- Patch:有三种Primitives对象rectangles, circles and polygons,在Figure.patch中
- Axes:Container对象,可通过
fig.axes
访问有关的axes对象
- Text:Primitives对象,即
fig.suptitle('Figure Title')
设定的标题
- Legend:Primitives对象
- Axes :只列三个
- Patch:同Figure,但在axes.patch中
- Lines:Primitives对象,ax.plot创造的,可通过ax.lines访问
- xaxis,yaxis : Container对象
- Axis 对象包括tick lines, the grid lines, the tick labels and the axis label.
- Tick对象包括tick and grid line instances, label instances for the upper and lower ticks
最后通过一个代码理解,Matplotlib这个库的代码逻辑:
创建Container对象,访问Container包含的对象,区分开Primitives与Containers对象,然后就可以精确访问与设置相关属性了。
fig = plt.figure() # 创建一个Figure对象
rect = fig.patch # 取出Figure对象这个Container包含的Patch对象
rect.set_facecolor('lightgoldenrodyellow') #设置Patch的color
# 调用Figure对象方法创建下一级Axes Container对象
ax1 = fig.add_axes([0.1, 0.3, 0.4, 0.4])
rect = ax1.patch # 取出Axes对象包含的patch对象
rect.set_facecolor('lightslategray') # patch是个Primitives对象
# 取出axis中的ticklabels与ticklines
for label in ax1.xaxis.get_ticklabels():
# label is a Text instance
label.set_color('red')
label.set_rotation(45) # label是个text对象,是Primitives
label.set_fontsize(16)
for line in ax1.yaxis.get_ticklines():
# line is a Line2D instance
line.set_color('green')
line.set_markersize(25) # line对象是Primitives
line.set_markeredgewidth(3)
plt.show()
总的来说,要熟练使用Matplotlib库还是有点麻烦的,不过知道了整个库的设计逻辑以及组织结构,调用起来查起来也相当快,代码应该也能看懂了,库API也会查了,美滋滋~
但还是很繁琐呀,因此下一篇就了解一下高度封装matplotlib的seaborn简易API,以及学习一些Examples。
列一下逻辑:
- 图的创建方式ax或者plt,如果只有一个图直接plt比较方便
- 一个图的基本构成,以及四个Container对象Figure、Axes、Axis、Tick
- Primitives对象如Text、Line、Markers等要查API才知道参数
- 剩下的可以遇到需求再学习了~