LoginSignup
20
19

More than 5 years have passed since last update.

matplotlibのグラフの配置と位置・サイズに関する一考察

Posted at

はじめに

matplotlibのグラフや画像サイズをいろいろ決めたくなったが、サブプロットした時の状態とかよくわかってなかった。ので調べた。

デフォルトパラメータは

import matplotlib as mpl

print(mpl.rcParams["figure.figsize"])
print(mpl.rcParams["figure.dpi"])
print([mpl.rcParams["figure.subplot." +  name]
       for name in ["left", "right", "top", "bottom", "wspace", "hspace"]])

[6.0, 4.0]
72.0
[0.125, 0.9, 0.88, 0.125, 0.2, 0.2]

このとき、

AxesSubplotがひとつ

その1

import matplotlib.pyplot as plt

fig = plt.figure(facecolor="skyblue")
ax = fig.add_subplot(111)

print(fig)
print(ax)
fig.savefig("1.png", facecolor="skyblue")
fig.savefig("1_tight.png", facecolor="skyblue", bbox_inches="tight")

jupyterのOut

Figure(432x288)
AxesSubplot(0.125,0.125;0.775x0.755)
1_j.png(379x252)

1.png

1.png(432x288)

1_tight.png

1_tight.png(379x252)

その2

fig = plt.figure(facecolor="skyblue", linewidth=100, edgecolor="green")
ax = fig.add_subplot(111, ylabel="ylabel")
fig.subplots_adjust(left=0, right=1, bottom=0.2, top=0.8)

print(fig)
print(ax)
fig.savefig("2.png", facecolor="skyblue", edgecolor="orange")
fig.savefig("2_tight.png", facecolor="skyblue", edgecolor="blue", bbox_inches="tight")

JupyterのOut

Figure(432x288)
AxesSubplot(0,0.2;1x0.6)
2_j.png

2.png

2.png

2_tight.png

2_tight.png

わかったこと

  • Figure.figsizeは「キャンバス」のサイズで、画像出力時は基本的にそのキャンバスが出力範囲となる、しかしキャンバスの外にもオブジェクト配置・描画は可能。と考えたい。
  • figsize×dpiのピクセルサイズの画像が出力される。
  • SubplotParamsFigure.subplots_adjust())は、キャンバス左下を(0,0)・右上を(1,1)として、Axesの位置を決める。上には載せていないが0未満や1以上も指定可能だった。
  • Axesのエリアはプロットする部分が基準。(デフォルトでは)何もしなくても軸ラベルや目盛りが描画されているがこいつらはAxesのエリアからはみ出ている。
  • Figure.savefig()で、bbox_inches="tight"するとオブジェクトが描画されている場所に合わせて(キャンバスの範囲は無視して)、画像を出力してくれる。
  • Figureの枠(edgecolorlinewidth)は、キャンバスではなく出力画像に対して適用される。
  • jupyterのインライン表示ではbbox_inches="tight"が指定された画像が表示される。

AxesSubplotが複数

その1

fig = plt.figure(facecolor="skyblue")
ax1 = fig.add_subplot(211, xlabel="xlabel")
ax2 = fig.add_subplot(212, xlabel="xlabel")
fig.subplots_adjust(bottom=0, left=0, top=1, right=1)

print(ax1)
print(ax2)
fig.savefig("3.png", facecolor="skyblue")

AxesSubplot(0,0.545455;1x0.454545)
AxesSubplot(0,0;1x0.454545)
3_tight.png

3.png

3.png

サイズが変な少数になった。計算すると縦は(ax1:余白:ax2)=(5:1:5)の割合で配置されたようだ。

その2

fig = plt.figure(facecolor="skyblue")
ax1 = fig.add_subplot(311, xlabel="xlabel")
ax2 = fig.add_subplot(312, xlabel="xlabel")
ax3 = fig.add_subplot(313, xlabel="xlabel")
fig.subplots_adjust(bottom=0, left=0, top=1, right=1)

print(ax1)
print(ax2)
print(ax3)
fig.savefig("4.png", facecolor="skyblue")

AxesSubplot(0,0.705882;1x0.294118)
AxesSubplot(0,0.352941;1x0.294118)
AxesSubplot(0,0;1x0.294118)
4_tight.png

4.png

4.png

サイズが変な少数になった。その1から予想して(ax1:余白:ax2:余白:ax3)=(5:1:5:1:5)の割合で配置されたとみる。
$5÷(5+1+5+1+5)=0.2941176...$なので予想通りっぽい。

その3

fig = plt.figure(facecolor="skyblue")
ax1 = fig.add_subplot(211, xlabel="xlabel")
ax2 = fig.add_subplot(212, xlabel="xlabel")
fig.subplots_adjust(bottom=0.25, left=0.25, top=0.75, right=0.75, hspace=2)

print(ax1)
print(ax2)
fig.savefig("5.png", facecolor="skyblue")

AxesSubplot(0.25,0.625;0.5x0.125)
AxesSubplot(0.25,0.25;0.5x0.125)
5_tight.png

5.png

5.png

わかったこと

  • Axesが1つの時の範囲(SubplotParamsの上下左右)を基準に分割される。キャンバスのサイズ基準ではない。
  • 各縦横は、(1:space:1:space: ... :1)の比で分割される(spaceはSubplotParamshspace或いはwspace)。

Tight Layout

その1

fig = plt.figure(facecolor="skyblue", tight_layout=dict(pad=0))
ax1 = fig.add_subplot(131, facecolor="blue")
ax2 = fig.add_subplot(132, facecolor="white")
ax3 = fig.add_subplot(133, facecolor="red")
fig.subplots_adjust(bottom=0, left=0, top=1, right=1, wspace=1)

print(ax1)
print(ax2)
print(ax3)
fig.savefig("6.png", facecolor="skyblue")

AxesSubplot(0,0;0.2x1)
AxesSubplot(0.4,0;0.2x1)
AxesSubplot(0.8,0;0.2x1)
6_tight.png(446x302)

6.png

6.png(432x288)

その2

fig = plt.figure(facecolor="skyblue", tight_layout=dict(pad=0))
ax1 = fig.add_subplot(131, facecolor="blue")
ax2 = fig.add_subplot(132, facecolor="white")
ax3 = fig.add_subplot(133, facecolor="red")
fig.subplots_adjust(bottom=0, left=0, top=1, right=1, wspace=0)

print(ax1)
print(ax2)
print(ax3)
fig.savefig("7.png", facecolor="skyblue")

AxesSubplot(0,0;0.333333x1)
AxesSubplot(0.333333,0;0.333333x1)
AxesSubplot(0.666667,0;0.333333x1)
7_tight.png(446x302)

7.png

7.png(432x288)

インライン表示はその1とその2で同じ結果。出力画像は6.pngに比べて7.pngは各プロットエリアの横幅が小さい(間の余白が広い)。
インライン表示と出力画像の間でもプロットエリアの大きさが異なる。

わからなかった

  • キャンバスと各オブジェクトに合わせて、各プロットエリアを拡大縮小しているっぽい。
  • その1(6.png)とその2(7.png)の違いは?bbox_inches="tight"の有無の違いは?
  • ちなみにFigure.subplots_adjust()Figure.add_subplot()を実行する順番は関係なかった。

ほかにもいろいろ試したが、「結果どうなるかよくわからないけど、とりあえずうまく配置してくれる」っていう感想になった。

Constrained Layout

tight_layout以上にわからなかったので略

20
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
19