Matplotlib tight_layout()は図のタイトルを考慮しません


208

matplotlibのFigureにサブタイトルを追加すると、サブプロットのタイトルによってオーバーレイされます。誰かがそれを簡単に処理する方法を知っていますか?私はそのtight_layout()機能を試しましたが、それは事態を悪化させるだけです。

例:

import numpy as np
import matplotlib.pyplot as plt

f = np.random.random(100)
g = np.random.random(100)
fig = plt.figure()
fig.suptitle('Long Suptitle', fontsize=24)
plt.subplot(121)
plt.plot(f)
plt.title('Very Long Title 1', fontsize=20)
plt.subplot(122)
plt.plot(g)
plt.title('Very Long Title 2', fontsize=20)
plt.tight_layout()
plt.show()

回答:


179

tight_layout次のように、呼び出しでサブプロットジオメトリを調整できます。

fig.tight_layout(rect=[0, 0.03, 1, 0.95])

ドキュメントに記載されているように(https://matplotlib.org/users/tight_layout_guide.html):

tight_layout()目盛りラベル、軸ラベル、およびタイトルのみを考慮します。したがって、他のアーティストが切り取られたり、重複したりする場合があります。


1
それは魅力のように機能しましたが、バウンディングボックスを指定するとどのように変化しますか?ドキュメントを読みましたが、あまりわかりませんでした。私に説明して頂ければ幸いです!ありがとう。
thepunitsingh 2017年

2
それぞれの数字の意味を四角で説明していただけませんか?ドキュメントには表示されませんでした。
スティーブン・

6
@stevenは、tight_layoutドキュメントを参照してください:[left, bottom, right, top] in normalized (0, 1) figure coordinates
soupault

1
正解tight_layout(rect=[0, 0.03, 1, 0.9])0.95ようにではなく、右端の値を下げることで、suptitleとAxesの間のスペースをさらに広げることができます。
ComFreek

1
jupyter内では機能しませんでした。数値にさまざまな値を試しても効果はありませんでした
Aleksejs Fomins

114

次を使用して手動で間隔を調整できますplt.subplots_adjust(top=0.85)

import numpy as np
import matplotlib.pyplot as plt

f = np.random.random(100)
g = np.random.random(100)
fig = plt.figure()
fig.suptitle('Long Suptitle', fontsize=24)
plt.subplot(121)
plt.plot(f)
plt.title('Very Long Title 1', fontsize=20)
plt.subplot(122)
plt.plot(g)
plt.title('Very Long Title 2', fontsize=20)
plt.subplots_adjust(top=0.85)
plt.show()

5
電話をかけるときのtopのデフォルト値は0.9であることに注意してくださいsubplots_adjust
Brian Burns

72
私たちの主の2017年を信じられません。これはまだmatplotlibのバグです。
言葉の言い方については、2017年

29
subplots_adjust呼び出さなければなりません後のすべての呼び出しにtight_layout、あるいは呼び出しの効果はかかりませんsubplots_adjust
Achal Dave 2017

7
@wordsforthewiseはその2018を今すぐ作る
vlsd

6
@vlsd 2019
Xiaoyu Lu

55

コードで非常に簡単に変更できることの1つfontsizeは、タイトルに使用しているものです。しかし、私はあなたがそれをしたくないだけだと思います!

を使用するいくつかの代替fig.subplots_adjust(top=0.85)

通常tight_layout()、すべてが適切な場所に配置され、重複しないように配置することで、かなりうまくいきます。その理由はtight_layout()ので、この場合のヘルプがあるしないtight_layout()口座に)(fig.suptitleかかりません。GitHubにはこれに関する未解決の問題があります:https : //github.com/matplotlib/matplotlib/issues/829 [完全なジオメトリマネージャーが必要なため2014年にクローズ-https: //github.com/matplotlib/matplotlib / issues / 1109 ]。

スレッドを読んだ場合、に関する問題の解決策がありますGridSpec。重要なのはtight_layoutrectkwarg を使用してを呼び出すときに、図の上部にスペースを空けることです。あなたの問題では、コードは次のようになります:

GridSpecの使用

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

f = np.random.random(100)
g = np.random.random(100)

fig = plt.figure(1)
gs1 = gridspec.GridSpec(1, 2)
ax_list = [fig.add_subplot(ss) for ss in gs1]

ax_list[0].plot(f)
ax_list[0].set_title('Very Long Title 1', fontsize=20)

ax_list[1].plot(g)
ax_list[1].set_title('Very Long Title 2', fontsize=20)

fig.suptitle('Long Suptitle', fontsize=24)    

gs1.tight_layout(fig, rect=[0, 0.03, 1, 0.95])  

plt.show()

結果:

gridspecの使用

多分GridSpecあなたにとって少しやり過ぎかもしれません、またはあなたの実際の問題ははるかに大きなキャンバス上の他のより多くのサブプロット、または他の合併症を伴うでしょう。単純なハックはannotate()、座標をに使用してロックし、'figure fraction'を模倣することsuptitleです。ただし、出力を確認したら、さらに細かい調整が必要になる場合があります。この2番目のソリューションは使用しないことに注意してくださいtight_layout()

よりシンプルなソリューション(微調整が必​​要場合があります)

fig = plt.figure(2)

ax1 = plt.subplot(121)
ax1.plot(f)
ax1.set_title('Very Long Title 1', fontsize=20)

ax2 = plt.subplot(122)
ax2.plot(g)
ax2.set_title('Very Long Title 2', fontsize=20)

# fig.suptitle('Long Suptitle', fontsize=24)
# Instead, do a hack by annotating the first axes with the desired 
# string and set the positioning to 'figure fraction'.
fig.get_axes()[0].annotate('Long Suptitle', (0.5, 0.95), 
                            xycoords='figure fraction', ha='center', 
                            fontsize=24
                            )
plt.show()

結果:

簡単な

[ Python2.7.3(64ビット)およびmatplotlib1.2.0を使用]


1
ありがとう、あなたが提案した最初のソリューションを使用する場合(を使用してGridSpec)、軸を共有するサブプロットをどのように作成できますか?私は通常plt.subplots(N,1, sharex=<>, sharey=<>)、サブプロットを作成するときに使用しますが、投稿したコードがadd_subplot代わりに使用します
Amelio Vazquez-Reina

10
キャスティングfig.tight_layout(rect=[0, 0.03, 1, 0.95])も機能します。
soupault

1
2番目の解決策は私のために働いた唯一のものです。ありがとうございました!
ハバード

19

別の簡単に使用できるソリューションは、suptitleの呼び出しでy引数を使用して、図のsuptitleテキストの座標を調整することです(docsを参照)。

import numpy as np
import matplotlib.pyplot as plt

f = np.random.random(100)
g = np.random.random(100)
fig = plt.figure()
fig.suptitle('Long Suptitle', y=1.05, fontsize=24)
plt.subplot(121)
plt.plot(f)
plt.title('Very Long Title 1', fontsize=20)
plt.subplot(122)
plt.plot(g)
plt.title('Very Long Title 2', fontsize=20)
plt.show()

8
これはノートブックでは優れた方法ですが、plt.savefig()コマンドは従いません。このソリューションは、savefigコマンドのタイトルを切り捨てます。
スーパーヒーロー

11

タイトなレイアウトは字幕では機能しませんが、constrained_layout機能します。この質問見るmatplotlibの多くのサブプロットでサブプロットのサイズ/間隔を改善する

サブプロットを一度に追加すると見栄えがよくなる、つまり

fig, axs = plt.subplots(rows, cols, constrained_layout=True)

# then iterating over the axes to fill in the plots

ただし、図が作成された時点で追加することもできます。

fig = plt.figure(constrained_layout=True)

ax1 = fig.add_subplot(cols, rows, 1)
# etc

注:サブプロットを近づけるために、

fig.subplots_adjust(wspace=0.05)

そして、constrained_layoutはこれでは機能しません:(


4

私はmatplotlibトリミングメソッドに苦労してきたのでbashImageMagick' mogrifyコマンドの呼び出しを介してこれを行う関数を作成しました。これには、UNIX / Linuxを使用していて、bashシェルを使用していて、ImageMagickインストールされている必要があります。

呼び出しの後にこれに呼び出しを投げるだけsavefig()です。

def autocrop_img(filename):
    '''Call ImageMagick mogrify from bash to autocrop image'''
    import subprocess
    import os

    cwd, img_name = os.path.split(filename)

    bashcmd = 'mogrify -trim %s' % img_name
    process = subprocess.Popen(bashcmd.split(), stdout=subprocess.PIPE, cwd=cwd)

3

他の人が述べたように、デフォルトでは、タイトなレイアウトは肩書きを考慮していません。ただし、bbox_extra_artists引数を使用して、考慮に入れるべき境界ボックスとしてサプリトを渡すことが可能であることがわかりました。

st = fig.suptitle("My Super Title")
plt.savefig("figure.png", bbox_extra_artists=[st], bbox_inches='tight')

これにより、厳密なレイアウト計算でがsuptitle考慮され、予想どおりに表示されます。


これが私にとって有効な唯一のオプションです。私はJupyterノートブックを使用して図を作成して保存します。LinuxマシンのPython 3.6で作業しています。
GRquanti

2

私のために働いた唯一のことはsuptitleへの呼び出しを変更することでした:

fig.suptitle("title", y=.995)

1

tight_layout非常に大きなプロットグリッド(200を超えるサブプロット)を使用し、jupyterノートブックでレンダリングすると、同様の問題が発生しました。私は常にあなたsuptitleをあなたの一番上のサブプロットの上の特定の距離に置く簡単な解決策を作りました:

import matplotlib.pyplot as plt

n_rows = 50
n_col = 4
fig, axs = plt.subplots(n_rows, n_cols)

#make plots ...

# define y position of suptitle to be ~20% of a row above the top row
y_title_pos = axs[0][0].get_position().get_points()[1][1]+(1/n_rows)*0.2
fig.suptitle('My Sup Title', y=y_title_pos)

可変サイズのサブプロットの場合でも、このメソッドを使用して最上位のサブプロットのトップを取得し、その後、字幕に追加する追加の量を手動で定義できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.