Warning: Undefined variable $position in /home/pystyles/pystyle.info/public_html/wp/wp-content/themes/lionblog/functions.php on line 4897

matplotlib – GridSpec で図の中に複数のグラフを作成する方法

matplotlib – GridSpec で図の中に複数のグラフを作成する方法

概要

matplotlib の GridSpec を使用して、1つの図に様々な大きさのグラフを追加する方法について解説します。

Advertisement

API

使い方

In [1]:
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec

fig = plt.figure()

# 1.
gs = GridSpec(3, 3)  # グリッド

# 2.
ss1 = gs.new_subplotspec((0, 0), colspan=2)  # ax1 を配置する領域
ss2 = gs.new_subplotspec((1, 0), rowspan=2, colspan=2)  # ax2 を配置する領域
ss3 = gs.new_subplotspec((0, 2), rowspan=3)  # ax3 を配置する領域

# 3.
ax1 = plt.subplot(ss1)
ax2 = plt.subplot(ss2)
ax3 = plt.subplot(ss3)

# デバッグ用
def make_ticklabels_invisible(fig):
    """目盛りを非表示にし、Axes の真ん中にテキストを追加する。"""
    for i, ax in enumerate(fig.axes, 1):
        ax.text(0.5, 0.5, "ax{}".format(i), fontsize=20, va="center", ha="center")
        for tl in ax.get_xticklabels() + ax.get_yticklabels():
            tl.set_visible(False)


make_ticklabels_invisible(fig)

コードについて解説します。 pyplot.GridSpec(num_rows, num_cols) で GridSpec オブジェクトを作成します。

gs = plt.GridSpec(4, 3)

GridSpec

GridSpec.new_subplotspec((i, j), rowspan=num_rows, colspan=num_cols) でグリッド上の Subplot を配置する領域を表す SubplotSpec オブジェクトを作成します。

ss1 = gs.new_subplotspec((0, 0), colspan=2)
ss2 = gs.new_subplotspec((1, 0), rowspan=2, colspan=2)
ss3 = gs.new_subplotspec((0, 2), rowspan=3)

SubplotSpec

SubplotSpec オブジェクトを pyplot.subplot() の第1引数に渡し、その領域に Axes を作成します。

ax1 = plt.subplot(ss1)
ax2 = plt.subplot(ss2)
ax3 = plt.subplot(ss3)

Axes

GridSpec オブジェクトの indexing を使う

GridSpec は pyplot.new_subplotspec() を使う代わりに、numpy 風のインデックスの指定により、グリッド上で Subplot を配置する領域を表す SubplotSpec オブジェクトを作成できます。

In [2]:
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec

fig = plt.figure()
gs = GridSpec(3, 3)
ax1 = plt.subplot(gs[0, :2])
ax2 = plt.subplot(gs[1:, :2])
ax3 = plt.subplot(gs[:, 2])

make_ticklabels_invisible(fig)

pyplot.subplot2grid() を使う

subplot2grid() は、グリッドの形状、グリッド上で Subplot を配置する領域を引数で指定して Axes を作成できるヘルパー関数です。

In [3]:
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=2)
ax2 = plt.subplot2grid((3, 3), (1, 0), rowspan=2, colspan=2)
ax3 = plt.subplot2grid((3, 3), (0, 2), rowspan=3)

make_ticklabels_invisible(fig)

余白を調整する

GridSpec の引数で余白を調整できます。

  • left, right, bottom, top は Figure 上に作成する GridSpec の領域を指定します。単位は Figure の左下が (0, 0)、右上が (1, 1) である座標系です。
  • wspace, hspace はそれぞれ Subplot 間の水平方向、垂直方向の余白を指定します。単位は wspace の場合は Axes の幅の平均に対する割合、hspace の場合は Axes の高さの平均に対する割合です。

余白の調整

In [4]:
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec

fig, ax = plt.subplots()
gs = GridSpec(3, 3, left=0.05, right=0.95, bottom=0.1, top=0.9, wspace=0.4, hspace=0.4)
ax1 = plt.subplot(gs[0, :2])
ax2 = plt.subplot(gs[1:, :2])
ax3 = plt.subplot(gs[:, 2:])

make_ticklabels_invisible(fig)

グリッドを入れ子にして作成する

GridSpecFromSubplotSpec を使うことで入れ子のグリッドを作成して、その領域に Axes を作成できます。

  1. GridSpec オブジェクトを作成します。
  2. GridSpec の指定した領域に GridSpecFromSubplotSpec オブジェクトを作成します。
  3. GridSpecFromSubplotSpec の指定した領域に Axes オブジェクトを作成します。

GridSpecFromSubplotSpec

In [5]:
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec, GridSpecFromSubplotSpec

fig = plt.figure()
# 1
gs0 = GridSpec(1, 2)
# 2
gs00 = GridSpecFromSubplotSpec(3, 3, subplot_spec=gs0[0])
gs01 = GridSpecFromSubplotSpec(3, 3, subplot_spec=gs0[1])
# 3
ax1 = plt.subplot(gs00[:-1, :])
ax2 = plt.subplot(gs00[-1, :-1])
ax3 = plt.subplot(gs00[-1, -1])
ax4 = plt.subplot(gs01[:, :-1])
ax5 = plt.subplot(gs01[:-1, -1])
ax6 = plt.subplot(gs01[-1, -1])

make_ticklabels_invisible(fig)
plt.show()

GridSpec の各セルの大きさを変更する

GridSpec の width_ratios, height_ratios でそれぞれグリッドを作成した際の列、行の長さの比率を指定できます。

GridSpecFromSubplotSpec

In [6]:
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec

fig = plt.figure()
gs = 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(fig)
plt.show()