matplotlibのすこしむずかしい配置

matplotlibを使って少し変化球な図の配置をしたのでその備忘録。Nested gridspecあたりでググったら出てくるはず

ゴール

f:id:bye-ron:20220331141831p:plain

方針

matplotlibの画像を配置するときは、図の複雑さに応じて次の順番で対応することが多い

  • 格子状に図を配置するとき
    • fig = plt.figure からの fig.subplots or fig.add_subplot
    • 基本はこれ
  • ゴールの図のように同じサイズでない格子が並ぶ場合
    • gridspec.GridSpecで大きな枠を作成し、gridspec.GridSpecFromSubplotSpecでその大きな枠の中にNestedな格子を作成する

コード(と補助資料)

f:id:bye-ron:20220331144756p:plain

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec


def main():
    # 見栄えの都合でこのサイズ
    x = 6.5 * 3
    y = 2.2 * 3
    fig = plt.figure(figsize=(x, y))

    # 2x2の大枠を作る
    gs = gridspec.GridSpec(
           2,
           2,
           figure=fig,
           width_ratios=[7, 3], # 左の図の比率を大きくする
           height_ratios=[4, 3] # 上の図の比率を大きくする
    )

    # 図中Aの位置(gs[0,0])に1x1の描画領域を作成
    gs_a = gridspec.GridSpecFromSubplotSpec(1, 1, subplot_spec=gs[0, 0])
    ax = fig.add_subplot(gs_a[0, 0])
    # ax.plot(hogehoge)

    # 図中Bの位置(gs[1,0])に1x6の描画領域を作成
    gs_b = gridspec.GridSpecFromSubplotSpec(1, 6, subplot_spec=gs[1, 0])
    for i in range(6):
        ax = fig.add_subplot(gs_b[0, i]).set_aspect("equal")
        # ax.plot(fugafuga)

    # 2x2の枠の2つをマージして1つの縦長の枠を作成できる
    gs_c = gridspec.GridSpecFromSubplotSpec(4, 1, subplot_spec=gs[0:2, 1]) 
    for i in range(4):
        ax = fig.add_subplot(gs_c[i, 0])
        # ax.plot(foobar)

    fig.tight_layout(pad=8) # 見栄えで余白を入れている
    plt.show()


if __name__ == "__main__":
    main()

おわり