Matplotlib tight_layout ()은 Figure Suptitle을 고려하지 않습니다.


208

matplotlib 그림에 자막을 추가하면 서브 플롯의 제목으로 자막이 표시됩니다. 아무도 그것을 쉽게 처리하는 방법을 알고 있습니까? 나는 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

2
각 숫자의 의미를 rect로 설명해 주시겠습니까? 나는 문서에서 그들을 보지 못했다.
스티븐

6
@ 스티븐 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같이 가장 오른쪽에있는 값을 낮추면 자막과 축 사이의 간격을 더 늘릴 수 있습니다 .
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의 버그입니다.
wordsforthewise

29
subplots_adjust호출 한 후에 호출 해야합니다. 그렇지 않으면 호출 tight_layout효과가 없습니다 subplots_adjust.
Achal Dave

7
@wordsforthewise는 2018을 지금 만드십시오
vlsd

6
@vlsd 2019 년 안녕하세요
Lu

55

코드에서 매우 쉽게 변경할 수있는 것은 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 / 문제 / 1109 ].

스레드를 읽으면 관련 문제에 대한 해결책이 있습니다 GridSpec. 핵심은 kwarg를 tight_layout사용 rect하여을 호출 할 때 그림의 맨 위에 약간의 공간을 두는 것입니다. 문제의 경우 코드는 다음과 같습니다.

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. 그러나 출력을 살펴본 후에는 미세 조정이 필요할 수 있습니다. 이 두 번째 솔루션은 사용 하지 않습니다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
두 번째 해결책은 나를 위해 일한 유일한 것입니다. 감사합니다!
Hagbard

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과 분투 bash를 호출 ImageMagickmogrify 명령 잘 작동하고 그림의 가장자리에 떨어져 모든 여분의 공백을 가져옵니다. 이를 위해서는 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인수 를 사용 하여 Suptitle을 경계 상자로 전달할 수 있다는 것을 알았습니다 .

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

나를 위해 일한 유일한 것은 자막 호출을 수정하는 것이 었습니다.

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)

가변 크기의 서브 플롯의 경우에도이 방법을 사용하여 최상위 서브 플롯의 맨 위를 가져온 다음 Suptitle에 추가 할 추가 금액을 수동으로 정의 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.