前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >matplotlib基础:使用GridSpec自定义子图

matplotlib基础:使用GridSpec自定义子图

作者头像
bugsuse
发布2020-04-21 17:44:23
4.1K0
发布2020-04-21 17:44:23
举报
文章被收录于专栏:气象杂货铺

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()
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-04-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 气象杂货铺 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档