IT story

matplotlib 서브 플롯에 대한 공통 xlabel / ylabel

hot-time 2020. 8. 7. 07:56
반응형

matplotlib 서브 플롯에 대한 공통 xlabel / ylabel


다음 플롯이 있습니다.

fig,ax = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)

이제이 플롯에 일반적인 x 축 레이블과 y 축 레이블을 지정하고 싶습니다. "공통"이란 서브 플롯의 전체 그리드 아래에 하나의 큰 x 축 레이블이 있어야하고 오른쪽에 하나의 큰 y 축 레이블이 있어야 함을 의미합니다. 에 대한 문서에서 이것에 대해 아무것도 찾을 수 없으며 plt.subplots인터넷 검색은 plt.subplot(111)시작하려면 크게 만들어야한다고 제안합니다. 하지만 5 * 2 서브 플롯을 사용하여 plt.subplots어떻게 넣을 수 있습니까?


이것은 실제로 원하는 것 같습니다. 이 답변 의 동일한 접근 방식을 특정 사례에 적용합니다 .

import matplotlib.pyplot as plt

fig, ax = plt.subplots(nrows=3, ncols=3, sharex=True, sharey=True, figsize=(6, 6))

fig.text(0.5, 0.04, 'common X', ha='center')
fig.text(0.04, 0.5, 'common Y', va='center', rotation='vertical')

공통 좌표축 레이블이있는 다중 플롯


sharex=True, sharey=True당신 없이 :

여기에 이미지 설명을 입력하십시오

그것으로 당신은 더 좋게 얻을 것입니다.

fig, axes2d = plt.subplots(nrows=3, ncols=3,
                           sharex=True, sharey=True,
                           figsize=(6,6))

for i, row in enumerate(axes2d):
    for j, cell in enumerate(row):
        cell.imshow(np.random.rand(32,32))

plt.tight_layout()

여기에 이미지 설명을 입력하십시오

그러나 추가 레이블을 추가하려면 가장자리 플롯에만 추가해야합니다.

fig, axes2d = plt.subplots(nrows=3, ncols=3,
                           sharex=True, sharey=True,
                           figsize=(6,6))

for i, row in enumerate(axes2d):
    for j, cell in enumerate(row):
        cell.imshow(np.random.rand(32,32))
        if i == len(axes2d) - 1:
            cell.set_xlabel("noise column: {0:d}".format(j + 1))
        if j == 0:
            cell.set_ylabel("noise row: {0:d}".format(i + 1))

plt.tight_layout()

여기에 이미지 설명을 입력하십시오

각 플롯에 대한 레이블을 추가하면이를 망칠 수 있습니다 (반복 된 레이블을 자동으로 감지하는 방법이있을 수 있지만 그 방법은 알지 못합니다).


관련성이 있고 우아하다고 생각하기 때문에 (텍스트를 배치하기 위해 좌표를 지정할 필요가 없음) 다른 관련 질문에 대한 답변을 복사합니다 (약간 조정하여) .

import matplotlib.pyplot as plt
fig, axes = plt.subplots(5, 2, sharex=True, sharey=True, figsize=(6,15))
# add a big axis, hide frame
fig.add_subplot(111, frameon=False)
# hide tick and tick label of the big axis
plt.tick_params(labelcolor='none', top=False, bottom=False, left=False, right=False)
plt.xlabel("common X")
plt.ylabel("common Y")

결과는 다음과 같습니다 (matplotlib 버전 2.2.0 사용).

공통 x 및 y 축 레이블이있는 5 개 행 및 2 개 열 서브 플롯


명령 이후 :

fig,ax = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)

당신은 (내가 변경 한 것을 마음처럼 뭔가를 이미 충분하다, 튜플은 그림과 축 인스턴스의 목록으로 구성된 수익률을 사용 fig,axfig,axes) :

fig,axes = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)

for ax in axes:
    ax.set_xlabel('Common x-label')
    ax.set_ylabel('Common y-label')

특정 서브 플롯의 일부 세부 사항을 변경하려는 경우 서브 플롯을 반복하는 axes[i]위치 를 통해 액세스 할 수 있습니다 i.

다음을 포함하는 것도 매우 도움이 될 수 있습니다.

fig.tight_layout()

plt.show()레이블이 겹치지 않도록 파일의 끝에서 .


왼쪽 하단 모서리에있는 서브 플롯에 대해 보이지 않는 레이블을 만들어 일반 레이블을위한 공간을 예약하면 더보기 좋습니다. rcParams에서 fontsize를 전달하는 것도 좋습니다. 이런 식으로 공통 레이블은 rc 설정에 따라 크기가 변경되고 축도 조정되어 공통 레이블을위한 공간을 남깁니다.

fig_size = [8, 6]
fig, ax = plt.subplots(5, 2, sharex=True, sharey=True, figsize=fig_size)
# Reserve space for axis labels
ax[-1, 0].set_xlabel('.', color=(0, 0, 0, 0))
ax[-1, 0].set_ylabel('.', color=(0, 0, 0, 0))
# Make common axis labels
fig.text(0.5, 0.04, 'common X', va='center', ha='center', fontsize=rcParams['axes.labelsize'])
fig.text(0.04, 0.5, 'common Y', va='center', ha='center', rotation='vertical', fontsize=rcParams['axes.labelsize'])

여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오


그래프 그리드를 그리는 동안 비슷한 문제가 발생했습니다. 그래프는 두 부분 (상단 및 하단)으로 구성됩니다. y 레이블은 두 부분의 중앙에 있어야합니다.

I did not want to use a solution that depends on knowing the position in the outer figure (like fig.text()), so I manipulated the y-position of the set_ylabel() function. It is usually 0.5, the middle of the plot it is added to. As the padding between the parts (hspace) in my code was zero, I could calculate the middle of the two parts relative to the upper part.

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

# Create outer and inner grid
outerGrid = gridspec.GridSpec(2, 3, width_ratios=[1,1,1], height_ratios=[1,1])
somePlot = gridspec.GridSpecFromSubplotSpec(2, 1,
               subplot_spec=outerGrid[3], height_ratios=[1,3], hspace = 0)

# Add two partial plots
partA = plt.subplot(somePlot[0])
partB = plt.subplot(somePlot[1])

# No x-ticks for the upper plot
plt.setp(partA.get_xticklabels(), visible=False)

# The center is (height(top)-height(bottom))/(2*height(top))
# Simplified to 0.5 - height(bottom)/(2*height(top))
mid = 0.5-somePlot.get_height_ratios()[1]/(2.*somePlot.get_height_ratios()[0])
# Place the y-label
partA.set_ylabel('shared label', y = mid)

plt.show()

picture

Downsides:

  • The horizontal distance to the plot is based on the top part, the bottom ticks might extend into the label.

  • The formula does not take space between the parts into account.

  • Throws an exception when the height of the top part is 0.

There is probably a general solution that takes padding between figures into account.


I discovered a more robust method:

If you know the bottom and top kwargs that went into a GridSpec initialization, or you otherwise know the edges positions of your axes in Figure coordinates, you can also specify the ylabel position in Figure coordinates with some fancy "transform" magic. For example:

import matplotlib.transforms as mtransforms
bottom, top = .1, .9
f, a = plt.subplots(nrows=2, ncols=1, bottom=bottom, top=top)
avepos = (bottom+top)/2
a[0].yaxis.label.set_transform(mtransforms.blended_transform_factory(
       mtransforms.IdentityTransform(), f.transFigure # specify x, y transform
       )) # changed from default blend (IdentityTransform(), a[0].transAxes)
a[0].yaxis.label.set_position((0, avepos))
a[0].set_ylabel('Hello, world!')

...and you should see that the label still appropriately adjusts left-right to keep from overlapping with ticklabels, just like normal -- but now it will adjust to be always exactly between the desired subplots.

또한을 사용하지 않으면 set_position기본적으로 ylabel이 Figure 중간에 정확히 표시됩니다 . 레이블이 마침내 그려 질 때 기본 좌표 변환이 변경되었는지 확인하지 않고 -coordinate에 matplotlib0.5를 사용 하기 때문이라고 생각합니다 y.

참고 URL : https://stackoverflow.com/questions/16150819/common-xlabel-ylabel-for-matplotlib-subplots

반응형