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

# はじめに

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

デフォルトパラメータは

```py
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

```py
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/5aa71d74-7c02-040c-a11e-d1fd62d53cb4.png)（379x252）

1.png

>![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/23fe7e6e-7c91-2163-1ea1-0c8939d3dd8c.png)（432x288）

1_tight.png

>![1_tight.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/645b8f81-8471-8d76-1c7d-e1a6bc38db70.png)（379x252）

## その2

```py
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/c53dc5e7-f80b-c756-e35a-c85b877a2129.png)


2.png

>![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/3b7d98a9-9f93-aaf5-8d0e-b7cd1ed183bf.png)


2_tight.png

>![2_tight.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/aac9d53a-9c6f-7052-32f5-ea7022fc66eb.png)


## わかったこと

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

# AxesSubplotが複数

## その1

```py
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/4bfffbad-ca07-6a00-6a65-b0572c94eef5.png)

3.png

>![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/92517dd6-99bf-17ed-cc17-f33de8334e75.png)

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

## その2

```py
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/b8ab3f44-c075-b00e-bda5-efbd9705cd38.png)

4.png

>![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/50633b38-803f-d586-3ee7-8aa4b4cef618.png)

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

## その3

```py
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/27ba9047-89ea-ae08-d278-9515d84fde9c.png)


5.png

>![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/98717dd5-2229-b9c6-fb53-48d88ebf81cf.png)


## わかったこと

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

# Tight Layout

## その1

```py
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/03c582ea-7ded-f5a8-6c0e-432f102454d9.png)（446x302）

6.png
>![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/cb963c9f-85e4-0001-e4da-461e07febcc6.png)（432x288）

## その2

```py
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](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/b5331127-753c-5fcf-2cd0-ad2b0ecc4d1d.png)（446x302）

7.png
>![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394333/72cfb44b-4428-e026-fa12-a47af673cc6a.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以上にわからなかったので略