Pythonでグラフを描くときにはMatplotlib
を使用することが多いですが…
fig, ax = plt.subplots()
って、よく見るけど何してるの?plt.subplots()
の便利な使い方を知りたい!
という方のために、
fig, ax = plt.subplots()
で、Figure
とAxes
を作ると何が便利なのか?plt.subplots()
の基本的な使い方- 覚えておくと便利な
plt.subplots()
の引数
を図解付きで解説していきます。
この記事を読むと、fig, ax = plt.subplots()
から始めるオブジェクト指向のグラフ作成がわかってくると思います!
- なぜplt.subplots()を使うのか?
- plt.subplots()の基本|FigureとAxesの生成方法
- Figureの見た目変更|plt.figure()のキーワード引数を指定
- サブプロット間でx軸、y軸を共有|sharex, sharey
- plt.subplots()まとめ
なぜplt.subplots()を使うのか?
Matplotlib
でグラフを描く際の基本パーツとしてFigure
とAxes
があります。
Figure
:描画領域全体Axes
:一つ一つのプロットを描く領域
Figure
やAxes
を一つずつ作成していく場合は、
fig = plt.figure()
⇒Figure
を生成fig.add_subplot()
⇒Axes
を1個ずつ追加 orfig.suplots()
⇒Axes
を複数追加
という手順を踏みます。
【補足】Figure
とAxes
の関係/操作方法について、詳しく知りたい方は次の記事をチェックしてください
しかし、Figure
だけ作成して、Axes
を作らないことってあまりないですよね。
結局両方作るなら、Figure
とAxes
を同時に作成できた方が便利です。
そんな時に便利なのが、
fig, ax = plt.subplots()
これでFigure
とAxes
を同時に生成できます。
この記事では、
plt.subplots()
の基本|Figure
とAxes
の生成方法- 覚えておくと便利な引数
Figure
の見た目変更方法- サブプロット間でx軸、y軸を共有する方法
を紹介していきます。
plt.subplots()の基本|FigureとAxesの生成方法
plt.subplots()
では、引数によって生成するAxes
(サブプロット)の数を変更できます。
fig, ax = plt.subplots()
引数を省力:1つのサブプロットを生成fig, axes = plt.subplots(nrows, ncols)
:nrows
×ncols
個のサブプロットを生成
次のサンプルデータを使用して、一つずつ紹介していきます。
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-3,3)
y = x**2
サンプルデータは、[-3,3]の範囲の二次曲線です。
np.linspace()
の詳細は、次の記事を参考にしてください。
サブプロットを一つ生成|fig, ax = plt.subplots()
引数を省略するとサブプロットが一つだけ生成されます。
fig, ax = plt.subplots()
ax.plot(x, y)
plt.show()
ax
を生成した後は、ax.XXX
を使用すれば様々な種類のグラフが描けます。
各種グラフの作成方法については、次の記事を参考にしてください。
- 折れ線グラフ:
ax..plot()
- 円グラフ:
ax..pie()
- 棒グラフ:
ax..bar()
- 散布図:
ax..scatter()
サブプロットを複数生成|fig, axes = subplots(nrows, ncols)
Figure
内に複数のサブプロットを配置したい場合は、
fig, axes = subplots(nrows, ncols)
のように引数でサブプロットの配置を指定します。この場合、
- 図を縦に
nrows
個、横にncols
個に分割 axes
に各Axes
オブジェクトを配列形式で格納
することになります。
例として、nrows=2
, ncols=3
で、サブプロットを作成してみます。
fig, axes = plt.subplots(2, 3, tight_layout=True)
plt.show()
次の図のように、
Figure
に2×3個のサブプロットを作成Axes
を2×3の配列内に格納
されます。
各サブプロットにグラフを描きたいときは、axes
の対応する要素のメソッドでグラフを描きます。
fig, axes = plt.subplots(2, 3, tight_layout=True)
axes[1,1].plot(x, y)
plt.show()
ここでは、tight_layout=True
を指定して、サブプロットのレイアウトを調整しています(次節で解説)。
サブプロットの位置指定はplt.subplot()
と同じ考え方なので、次の記事も参考にしてください。
axesを1次元配列で出力
fig, axes = subplots(nrows, ncols)
でaxes
を生成すると、サブプロットの配置によってaxes
の形状が自動で調整されます。
nrows>1
,ncols>1
⇒ 二次元配列(サイズ:nrows*ncols
)nrows=1
,nrows>1
⇒ 一次元配列(サイズ:ncols
)ncols=1
,nrows>1
⇒ 一次元配列(サイズ:nrows
)ncols=nrows=1
⇒ ゼロ次元配列(Axesオブジェクト
そのもの)
これは直感的でわかりやすい一方、配列の形状が変わってしまうと不便な場合もあります。
例えば、次のようなコードでは、列数nrows
, 行数ncols
のどちらかが1になるとエラーになります。
nrows=2
ncols=1
fig, axes = plt.subplots(nrows=nrows, ncols=ncols, tight_layout=True)
for i in range(nrows):
for j in range(ncols):
axes[i,j].plot(x, y)
# IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed
nrows=1
or ncols=1
のとき、axes
が一次元配列になるのでaxes[i]
と書かないとエラーになります。
このためだけにif文
で場合分けをするのはややめんどうです。
そういった場合は、
squeeze=False
を指定すると、axes
が常に二次元配列で生成されます。
列数nrows
, 行数ncols
によらず配列axes
の形状が一定なので、場合分けが不要になりますね。
nrows=2
ncols=1
# squeeze=Falseとしておけば、ncols=1でもaxes[i,j]と書ける
fig, axes = plt.subplots(nrows=nrows, ncols=ncols, squeeze=False, tight_layout=True)
for i in range(nrows):
for j in range(ncols):
axes[i,j].plot(x, y)
axes[i,j].set_title(f"plot({i}, {j})")
plt.show()
nrows=1 or ncols=1でも対応可能になりました。これは結構便利です。
Figureの見た目変更|plt.figure()のキーワード引数を指定
plt.subplots()
に、plt.figure()
の引数をキーワード引数で与えてFigure
の見た目を設定することもできます。
plt.subplots(figsize = (5, 5), tight_layout=True)
など
fig, axes = plt.subplots(2,2, figsize=(5,5), tight_layout=True, facecolor="whitesmoke")
plt.show()
覚えておくと便利なplt.figure()
のキーワード引数をまとめました。
設定内容 | 引数名 | 引数の指定方法 |
---|---|---|
描画領域のサイズ変更 | figsize |
(width, height) をインチで指定デフォルト: (6.4, 4.8) |
サブプロットのレイアウト自動調整 | tight_layout |
True or False デフォルト: False True にすると自動調整 |
描画領域の背景色変更 | facecolor |
色名などで指定 デフォルト: 'white' |
描画領域の枠線表示 | linewidth edgecolor |
linewidth = 数値pt edgecolor = '色名など' |
各引数の詳しい使い方は、次の記事をチェックしてください。
特にサブプロットのレイアウトを自動調整するtight_layout=True
はぜひ覚えてほしい引数です。
サブプロット間でx軸、y軸を共有|sharex, sharey
plt.subplots()
で作成したAxes
の軸は、それぞれのAxes
で個別に自動調整されます。
そのため、Axes
ごとに軸の最大値/最小値が異なり、Axes
間でのデータ比較が難しくなってしまう場合があります。
次の例では、Axes
ごとにy軸の最大値が自動調整されている例です。
fig, axes = plt.subplots(2, 2, tight_layout=True)
axes[0,0].plot(x, y)
axes[0,1].plot(x, 2*y)
axes[1,0].plot(x, 3*y)
axes[1,1].plot(x, 4*y)
plt.show()
一見すると全て同じグラフに見えてしまいますね。
こういった場合は
sharex
:Axes
間でx軸を共有sharey
:Axes
間でy軸を共有
するとデータの比較がしやすくなります。
sharex, shareyの使用例
次の例ではsharey="all"
を指定して、全てのAxes
でy軸を共有しています。
fig, axes = plt.subplots(2, 2, sharey = "all", tight_layout=True)
axes[0,0].plot(x, y)
axes[0,1].plot(x, 2*y)
axes[1,0].plot(x, 3*y)
axes[1,1].plot(x, 4*y)
plt.show()
sharex, shareyの指定方法
sharex
, sharey
はそれぞれ
sharex = XXX
:x軸の共有設定sharey = XXX
:y軸の共有設定
に対応しており、次の3種類の値を指定できます。
指定値 | 内容 |
---|---|
"all" |
全てのAxes で軸を共有 |
"row" |
同じ行内のAxes で軸を共有 |
"col" |
同じ列内のAxes で軸を共有 |
各指定値の組み合わせ例を確認していきましょう。
- 全ての
Axes
でx軸/y軸を共有
fig, axes = plt.subplots(2, 2, sharex="all", sharey = "all", tight_layout=True)
axes[0,0].plot(x, y)
axes[0,1].plot(2*x, 2*y)
axes[1,0].plot(3*x, 3*y)
axes[1,1].plot(4*x, 4*y)
plt.show()
- 同じ行内の
Axes
でy軸を共有
fig, axes = plt.subplots(2, 2, sharey="row", tight_layout=True)
axes[0,0].plot(x, y)
axes[0,1].plot(x, 2*y)
axes[1,0].plot(x, 3*y)
axes[1,1].plot(x, 4*y)
plt.show()
行ごとにy軸が共有されていますね。
- 同じ列内の
Axes
でx軸を共有
fig, axes = plt.subplots(2, 2, sharex="col", tight_layout=True)
axes[0,0].plot(x, y)
axes[0,1].plot(2*x, y)
axes[1,0].plot(3*x, y)
axes[1,1].plot(4*x, y)
plt.show()
左列グループ、右列グループでそれぞれx軸が共有されています。
plt.subplots()まとめ
今回は、plt.subplots()の使い方について整理しました。
fig, ax = plt.subplots()
を使用すれば、FigureとAxesを同時に作成できて便利なことが多いことがわかって頂けたと思います。
Matplotlib
のオブジェクト指向でのグラフ作成のポイントがわかってきますね。
もっとMatplotlib
を自由自在に操作したい!という方へのおススメコンテンツはこちらです!
Twitter@YutaKaでは、ほぼ毎日pythonに関する情報を発信しています。
気楽にツイートしているので、気軽にフォローしてください!