在pyplot模块中,与调整子图布局的函数主要为subplots_adjust
和tight_layout
,其中subplots_adjust
是修改子图间距的通用函数,tight_layout
默认执行一种固定的间距配置,也可以自定义间距配置,底层原理类似于subplots_adjust
函数。
subplots_adjust
函数概述
subplots_adjust
函数的功能为调整子图的布局参数。对于没有设置的参数保持不变,初始值由rcParams["figure.subplot.[name]"]
提供。
函数的签名为matplotlib.pyplot.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
函数的参数如下:
left
:所有子图整体相对于图像的左外边距,距离单位为图像宽度的比例(小数)。可选参数。浮点数。默认值为0.125
。right
:所有子图整体相对于图像的右外边距,距离单位为图像宽度的比例(小数)。可选参数。浮点数。默认值为0.0
。bottom
:所有子图整体相对于图像的下外边距,距离单位为图像高度的比例(小数)。可选参数。浮点数。默认值为0.11
。top
:所有子图整体相对于图像的上外边距,距离单位为图像高度的比例(小数)。可选参数。浮点数。默认值为0.88
。wspace
:子图间宽度内边距,距离单位为子图平均宽度的比例(小数)。浮点数。默认值为0.2
。hspace
:子图间高度内边距,距离单位为子图平均高度的比例(小数)。可选参数。浮点数。默认值为0.2
。
rcParams["figure.subplot.[name]"]
的值如下:
## The figure subplot parameters. All dimensions are a fraction of the figure width and height.
#figure.subplot.left: 0.125 # the left side of the subplots of the figure
#figure.subplot.right: 0.9 # the right side of the subplots of the figure
#figure.subplot.bottom: 0.11 # the bottom of the subplots of the figure
#figure.subplot.top: 0.88 # the top of the subplots of the figure
#figure.subplot.wspace: 0.2 # the amount of width reserved for space between subplots,
# expressed as a fraction of the average axis width
#figure.subplot.hspace: 0.2 # the amount of height reserved for space between subplots,
# expressed as a fraction of the average axis height
subplots_adjust
函数原理
根据以下源码可知,子图间距的默认设置即rcParams["figure.subplot.[name]"]
,使用subplots_adjust
函数调整后,间距配置保存在figure.subplotpars
。
pyplot.subplots_adjust()
源码
def subplots_adjust(
left=None, bottom=None, right=None, top=None, wspace=None,
hspace=None):
return gcf().subplots_adjust(
left=left, bottom=bottom, right=right, top=top, wspace=wspace,
hspace=hspace)
figure.Figure.subplots_adjust()
源码
def subplots_adjust(self, left=None, bottom=None, right=None, top=None,
wspace=None, hspace=None):
if self.get_constrained_layout():
self.set_constrained_layout(False)
_api.warn_external(
"This figure was using constrained_layout, but that is "
"incompatible with subplots_adjust and/or tight_layout; "
"disabling constrained_layout.")
self.subplotpars.update(left, bottom, right, top, wspace, hspace)
for ax in self.axes:
if isinstance(ax, SubplotBase):
ax._set_position(ax.get_subplotspec().get_position(self))
self.stale = True
figure.Figure.__init__()
源码
if subplotpars is None:
subplotpars = SubplotParams()
self.subplotpars = subplotpars
figure.SubplotParams
类源码
class SubplotParams:
"""
A class to hold the parameters for a subplot.
"""
def __init__(self, left=None, bottom=None, right=None, top=None,
wspace=None, hspace=None):
self.validate = True
for key in ["left", "bottom", "right", "top", "wspace", "hspace"]:
setattr(self, key, mpl.rcParams[f"figure.subplot.{key}"])
self.update(left, bottom, right, top, wspace, hspace)
def update(self, left=None, bottom=None, right=None, top=None,
wspace=None, hspace=None):
"""
Update the dimensions of the passed parameters. *None* means unchanged.
"""
if self.validate:
if ((left if left is not None else self.left)
>= (right if right is not None else self.right)):
raise ValueError('left cannot be >= right')
if ((bottom if bottom is not None else self.bottom)
>= (top if top is not None else self.top)):
raise ValueError('bottom cannot be >= top')
if left is not None:
self.left = left
if right is not None:
self.right = right
if bottom is not None:
self.bottom = bottom
if top is not None:
self.top = top
if wspace is not None:
self.wspace = wspace
if hspace is not None:
self.hspace = hspace
案例:subplots_adjust()
修改间距验证
import matplotlib.pyplot as plt
# 原始间距配置
fig,ax=plt.subplots(3,3)
print(vars(fig.subplotpars))
# 通过subplots_adjust()设置间距配置
plt.subplots_adjust(left=0.1,bottom=0.1,right=0.9,top=0.9,wspace=0.1,hspace=0.1)
print(vars(fig.subplotpars))
plt.show()
输出:
{'validate': True, 'left': 0.125, 'bottom': 0.125, 'right': 0.9, 'top': 0.88, 'wspace': 0.2, 'hspace': 0.2}
{'validate': True, 'left': 0.1, 'bottom': 0.1, 'right': 0.9, 'top': 0.9, 'wspace': 0.1, 'hspace': 0.1}
原始间距设置
subplots_adjust()
修改间距后
tight_layout
函数概述
tight_layout
函数的功能为子图的内边距。备注:对axes()
函数生成的子图无效。
函数的签名为matplotlib.pyplot.tight_layout(*, pad=1.08, h_pad=None, w_pad=None, rect=None)
函数的参数如下:
pad
:所有子图整体边缘相对于图像边缘的内边距,距离单位为字体大小的比例(小数,与rcParams["font.size"]
相关)。可选参数。浮点数。默认值为1.08
。h_pad, w_pad
:子图之间的内边距,距离单位为字体大小的比例(小数)。可选参数。浮点数。默认值为pad
。rect
:绘制子图的矩形区域的归一化坐标。可选参数。4元组(left, bottom, right, top)
。默认值为(0, 0, 1, 1)
。
tight_layout
函数原理
根据以下源码可知pyplot.tight_layout()
函数主要通过matplotlib.tight_layout
模块相关函数构造子图间距设置,最终通过figure.Figure.subplots_adjust
函数更新设置。
pyplot.tight_layout()
源码
def tight_layout(pad=1.08, h_pad=None, w_pad=None, rect=None):
gcf().tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad, rect=rect)
figure.Figure.tight_layout()
源码
def tight_layout(self, *, pad=1.08, h_pad=None, w_pad=None, rect=None):
from .tight_layout import (
get_renderer, get_subplotspec_list, get_tight_layout_figure)
from contextlib import suppress
subplotspec_list = get_subplotspec_list(self.axes)
if None in subplotspec_list:
_api.warn_external("This figure includes Axes that are not "
"compatible with tight_layout, so results "
"might be incorrect.")
renderer = get_renderer(self)
ctx = (renderer._draw_disabled()
if hasattr(renderer, '_draw_disabled')
else suppress())
with ctx:
kwargs = get_tight_layout_figure(
self, self.axes, subplotspec_list, renderer,
pad=pad, h_pad=h_pad, w_pad=w_pad, rect=rect)
if kwargs:
self.subplots_adjust(**kwargs)
案例:应用tight_layout
后验证间距配置
import matplotlib.pyplot as plt
# 原始间距配置
fig,ax=plt.subplots(3,3)
print(vars(fig.subplotpars))
# 设置tight_layout之后的默认间距配置
plt.tight_layout()
print(vars(fig.subplotpars))
# 设置tight_layout内边距之后的间距配置
plt.tight_layout(h_pad=2.5,w_pad=2.5)
print(vars(fig.subplotpars))
plt.show()
输出为:
{'validate': True, 'left': 0.125, 'bottom': 0.125, 'right': 0.9, 'top': 0.88, 'wspace': 0.2, 'hspace': 0.2}
{'validate': True, 'left': 0.0779513888888889, 'bottom': 0.09652777777777778, 'right': 0.9566261574074074, 'top': 0.9486111111111112, 'wspace': 0.42123244337593335, 'hspace': 0.5247524752475248}
{'validate': True, 'left': 0.0779513888888889, 'bottom': 0.0965277777777778, 'right': 0.9566261574074075, 'top': 0.9486111111111111, 'wspace': 0.6248542240052247, 'hspace': 0.8996088657105613}
扩展
通过设置rcParams['figure.autolayout']=True
可图像自动应用tight_layout
。
## Figure layout
#figure.autolayout: False # When True, automatically adjust subplot
# parameters to make the plot fit the figure
# using `tight_layout`
#figure.constrained_layout.use: False # When True, automatically make plot
# elements fit on the figure. (Not
# compatible with `autolayout`, above).
#figure.constrained_layout.h_pad: 0.04167 # Padding around axes objects. Float representing
#figure.constrained_layout.w_pad: 0.04167 # inches. Default is 3/72 inches (3 points)
#figure.constrained_layout.hspace: 0.02 # Space between subplot groups. Float representing
#figure.constrained_layout.wspace: 0.02 # a fraction of the subplot widths being separated.