GridSpec
指定绘制子图的网格形状,同时要设置绘制子图的行列数。当然也可以调整子图的布局(如 left,right等)。
SubplotSpec
确定由 GridSpec 指定的子图位置
subplot2grid
类似 pyplot.subplot 的非常有用的函数,但以 0 为起始
使用 subplot2grid 创建子图
使用 subplot2grid 时, 需要提供网格的几何形状及子图在网格中的位置。
先创建一个子图(即创建2行2列子图,并绘制第一个子图):
代码语言:javascript复制ax = plt.subplot2grid((2,2),(0, 0))
等同于
代码语言:javascript复制ax = plt.subplot(2,2,1)
注意: gridspec 的索引是以 0 为起始的,这一点和 subplot 不同。
下面创建含具有多个单元的子图:
完整代码:
代码语言:javascript复制import matplotlib.pyplot as plt
def make_ticklabels_invisible(fig):
for i, ax in enumerate(fig.axes):
ax.text(0.5, 0.5, "ax%d" % (i 1), va="center", ha="center")
for tl in ax.get_xticklabels() ax.get_yticklabels():
tl.set_visible(False)
plt.figure(0)
#创建3x3的子图,并且布局从第1行,第1列开始,占据3列,就是说整个第一行被我承包了
ax1 = plt.subplot2grid((3,3), (0,0), colspan=3)
#创建3x3的子图,并且布局从第2行,第1列开始,占据2列
ax2 = plt.subplot2grid((3,3), (1,0), colspan=2)
#创建3x3的子图,并且布局从第2行,第3列开始,占据2行
ax3 = plt.subplot2grid((3,3), (1, 2), rowspan=2)
#创建3x3的子图,并且布局从第3行,第1列开始,占据1行
ax4 = plt.subplot2grid((3,3), (2, 0))
#创建3x3的子图,并且布局从第3行,第2列开始,占据1行
ax5 = plt.subplot2grid((3,3), (2, 1))
plt.suptitle("subplot2grid")
make_ticklabels_invisible(plt.gcf())
plt.show()
GridSpec 和 SubplotSpec
当然也可以直接使用 GridSpec,然后创建子图
比如:
代码语言:javascript复制ax = plt.subplot2grid((2,2),(0, 0))
相当于
代码语言:javascript复制import matplotlib.gridspec as gridspec
gs = gridspec.GridSpec(2, 2)
ax = plt.subplot(gs[0, 0])
gridspec 实例提供类数组操作,并且返回 SubplotSpec 实例。SubplotSpec 可以分隔多个单元:
比如:
代码语言:javascript复制# 创建 3x3 的子图
gs = gridspec.GridSpec(3, 3)
# 承包整个第1行
ax1 = plt.subplot(gs[0, :])
# 承包第2行,前2列
ax2 = plt.subplot(gs[1,:-1])
# 承包2-3行,第3列
ax3 = plt.subplot(gs[1:, -1])
# 那我只能承包第3行第1列了,要不然 ax5 就没了
ax4 = plt.subplot(gs[-1,0])
# ...
ax5 = plt.subplot(gs[-1,-2])
完整代码如下:
代码语言:javascript复制import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
def make_ticklabels_invisible(fig):
for i, ax in enumerate(fig.axes):
ax.text(0.5, 0.5, "ax%d" % (i 1), va="center", ha="center")
for tl in ax.get_xticklabels() ax.get_yticklabels():
tl.set_visible(False)
plt.figure()
gs = GridSpec(3, 3)
ax1 = plt.subplot(gs[0, :])
# 和 ax1 = plt.subplot(gs.new_subplotspec((0,0), colspan=3)) 相同
ax2 = plt.subplot(gs[1,:-1])
ax3 = plt.subplot(gs[1:, -1])
ax4 = plt.subplot(gs[-1,0])
ax5 = plt.subplot(gs[-1,-2])
plt.suptitle("GridSpec")
make_ticklabels_invisible(plt.gcf())
plt.show()
调整 GridSpec 布局
当直接使用 GridSpec 创建子图时,可以调整其布局参数创建更合适的子图(直接使用 update 方法更新)
代码语言:javascript复制gs1 = gridspec.GridSpec(3, 3)
gs1.update(left=0.05, right=0.48, wspace=0.05)
类似 subplots_adjust() ,但是仅能作用于 GridSpec 创建的子图。
代码语言:javascript复制import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
# demo 3 : gridspec with subplotpars set.
f = plt.figure()
plt.suptitle("GridSpec w/ different subplotpars")
gs1 = GridSpec(3, 3)
gs1.update(left=0.05, right=0.48, wspace=0.05)
ax1 = plt.subplot(gs1[:-1, :])
ax2 = plt.subplot(gs1[-1, :-1])
ax3 = plt.subplot(gs1[-1, -1])
gs2 = GridSpec(3, 3)
gs2.update(left=0.55, right=0.98, hspace=0.05)
ax4 = plt.subplot(gs2[:, :-1])
ax5 = plt.subplot(gs2[:-1, -1])
ax6 = plt.subplot(gs2[-1, -1])
make_ticklabels_invisible(plt.gcf())
plt.show()
代码语言:javascript复制
使用 SubplotSpec
也可以通过 SubplotSpec 创建子图。这时候其布局参数将设置为 SubplotSpec 给定的位置。
代码语言:javascript复制import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
# gridspec 嵌套 gridspec
f = plt.figure()
gs0 = gridspec.GridSpec(1, 2)
gs00 = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=gs0[0])
ax1 = plt.Subplot(f, gs00[:-1, :])
f.add_subplot(ax1)
ax2 = plt.Subplot(f, gs00[-1, :-1])
f.add_subplot(ax2)
ax3 = plt.Subplot(f, gs00[-1, -1])
f.add_subplot(ax3)
gs01 = gridspec.GridSpecFromSubplotSpec(3, 3, subplot_spec=gs0[1])
ax4 = plt.Subplot(f, gs01[:, :-1])
f.add_subplot(ax4)
ax5 = plt.Subplot(f, gs01[:-1, -1])
f.add_subplot(ax5)
ax6 = plt.Subplot(f, gs01[-1, -1])
f.add_subplot(ax6)
plt.suptitle("GirdSpec Inside GridSpec")
make_ticklabels_invisible(plt.gcf())
plt.show()
使用 SubplotSpec 嵌套 GridSpec
下面给出一个更复杂的子图示例,最外围是 4x4 的子图,每个图中又含有 3x3 的子图,但3X3的子图的 spine 被隐藏了
代码语言:javascript复制import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np
try:
from itertools import product
except ImportError:
def product(*args, **kwds):
pools = map(tuple, args) * kwds.get('repeat', 1)
result = [[]]
for pool in pools:
result = [x [y] for x in result for y in pool]
for prod in result:
yield tuple(prod)
def squiggle_xy(a, b, c, d, i=np.arange(0.0, 2*np.pi, 0.05)):
return np.sin(i*a)*np.cos(i*b), np.sin(i*c)*np.cos(i*d)
fig = plt.figure(figsize=(8, 8))
# gridspec 嵌套 gridspec
outer_grid = gridspec.GridSpec(4, 4, wspace=0.0, hspace=0.0)
for i in range(16):
inner_grid = gridspec.GridSpecFromSubplotSpec(3, 3,
subplot_spec=outer_grid[i], wspace=0.0, hspace=0.0)
a, b = int(i/4) 1,i%4 1
for j, (c, d) in enumerate(product(range(1, 4), repeat=2)):
ax = plt.Subplot(fig, inner_grid[j])
ax.plot(*squiggle_xy(a, b, c, d))
ax.set_xticks([])
ax.set_yticks([])
fig.add_subplot(ax)
plt.show()
如果再添加下面的语句
代码语言:javascript复制for ax in all_axes:
for sp in ax.spines.values():
sp.set_visible(False)
if ax.is_first_row():
ax.spines['top'].set_visible(True)
if ax.is_last_row():
ax.spines['bottom'].set_visible(True)
if ax.is_first_col():
ax.spines['left'].set_visible(True)
if ax.is_last_col():
ax.spines['right'].set_visible(True)
plt.show()
使用 GridSpec 绘制不同尺寸的子图
代码语言:javascript复制import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
f = plt.figure()
gs = gridspec.GridSpec(2, 2,
width_ratios=[1,2],
height_ratios=[4,1]
)
ax1 = plt.subplot(gs[0])
ax2 = plt.subplot(gs[1])
ax3 = plt.subplot(gs[2])
ax4 = plt.subplot(gs[3])
make_ticklabels_invisible(f)
plt.show()