matplotlib 서브 플로트에 대한 일반적인 xlabel / ylabel


143

나는 다음과 같은 줄거리를 가지고있다 :

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어떻게 사용 합니까?


2
질문에 대한 업데이트와 함께 아래 답변에 남겨진 의견은 stackoverflow.com/questions/6963035/…
Hooked

실제로, 내 질문은 plt.subplots ()에 대한 것이고 귀하가 링크하는 질문은 add_subplot을 사용하므로 add_subplot으로 전환하지 않으면 해당 메소드를 사용할 수 없습니다. 내가 할 수 귀하의 링크에 대체 솔루션으로 주어진 plt.text 솔루션을 사용하지만, 가장 좋은 솔루션은 아닙니다.
jolindbe

내가 이해하는 한, plt.subplots는 기존 축 환경 내에서 subplots 세트를 생성 할 수 없지만 항상 새 그림을 작성합니다. 권리?
jolindbe

가장 우아한 솔루션은 여기에서 찾을 수 있습니다 : stackoverflow.com/questions/6963035/…
Mr.H

귀하의 링크는 사용자에 의해 제공되었습니다. 앞에서 말했듯이 그 솔루션은 plt.subplots ()가 아니라 add_subplot과 관련이 있습니다.
jolindbe

답변:


206

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

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')

공통 축 레이블이있는 여러 플롯


4
x- 라벨의 x 좌표에 대해 0.5는 레이블을 중앙 서브 플롯의 중심에 놓지 않습니다. yticklabels를 설명하기 위해 그것보다 약간 더 커야합니다.
dbliss

2
를 사용하지 않는 방법에 대해서는 이 답변 을 살펴보십시오 plt.text. 서브 플롯을 생성 한 다음 하나의 비트 플롯을 추가하여 보이지 않게하고 x 및 y 레이블을 지정합니다.
James Owers

고마워, 일반적으로 일했다. 사용시 파손에 대한 해결책 tight_layout?
serv-inc

3
@ serv-inc로 tight_layout교체 하면 작동 0.04하는 0것 같습니다.
divenex

3
사용 fig.text하는 것은 좋은 생각이 아닙니다. 이것은 다음과 같은 것들을 plt.tight_layout()
Peaceful

55

텍스트를 배치하기 위해 좌표를 지정할 필요가없는 관련성과 우아함을 고려하기 때문에 다른 관련 질문에 대한 답변을 약간 수정하여 복사 합니다.

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 개의 열 서브 플롯


4
단순하기 때문에 이것이 정답입니다. 매우 간단합니다. matplotlib v3.x와 관련이 있습니다.
Kyle Swanson

여러 그림 개체와 함께 어떻게 사용할 수 있는지 알고 싶습니다. fig.xlabel ( "foo")가 작동하지 않습니다.
공포 Vacui

참고 : 이제 사람들에 유래 어두운 테마를 사용하는 것이, 라벨은 거의 그것의 더 나은 내보낼 수 있도록 읽을 수 있습니다 흰색 배경와 PNG의
xyzzyqed

@xyzzyqed 나는 stackoverflow에 "테마"와 같은 것이 있다는 것을 몰랐으며, 그림을 내 보낸 방법조차 기억하지 못한다. 내보낼 때 배경을 어떻게 제어 할 수 있습니까?
14:01의

2
이 솔루션의 유일한 문제점 constrained_layout=True은 겹치는 레이블을 작성하기 때문에 사용할 때 작동하지 않는다는 것 입니다. 이 경우 하위 그림의 경계를 수동으로 조정해야합니다.
baccandr

35

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()

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

각 플롯에 레이블을 추가하면 레이블이 손상 될 수 있습니다 (반복 된 레이블을 자동으로 감지하는 방법이있을 수 있지만 알 수는 없습니다).


예를 들어, 플롯 수를 알 수없는 경우 (예 : 여러 하위 플롯에 대해 작동하는 일반화 플롯 기능이있는 경우) 훨씬 어렵습니다.
naught101

15

명령 이후 :

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()라벨이 겹치지 않도록 파일 끝에서 .


5
위의 내용이 불분명해서 죄송합니다. "공통"을 사용하여 모든 플롯 아래에 하나의 단일 x 레이블을, 플롯 왼쪽에 하나의 단일 y 레이블을 의미하여 이것을 반영하도록 질문을 업데이트했습니다.
jolindbe

2
@JohanLindberg : 여기와 위에서 여러분의 의견에 대하여 : 실제로 plt.subplots()새로운 그림 인스턴스를 만들 것입니다. 이 명령을 사용 big_ax = fig.add_subplot(111)하려면 이미 그림이 있고 다른 축을 추가 할 수 있으므로을 쉽게 추가 할 수 있습니다 . 그런 다음 big_axHooked의 링크에 표시되는 방식을 조작 할 수 있습니다 .
Marius

귀하의 제안에 감사하지만, 그렇게하면 plt.subplots () 뒤에 big_ax를 추가해야하며 그 하위 플롯을 다른 모든 것 위에 추가해야합니다. 투명하게 만들거나 어떻게 든 뒤로 보낼 수 있습니까? Hooked의 링크에서와 같이 모든 색상을 none으로 설정하더라도 여전히 모든 하위 플롯을 덮는 흰색 상자입니다.
jolindbe

2
@JohanLindberg, 당신 말이 맞아요, 나는 그것을 확인하지 않았습니다. 그러나 당신은 쉽게 큰 축 배경 색상을 설정할 수 있습니다 none수행하여 : big_ax.set_axis_bgcolor('none')당신은 또한 labelcolor을해야한다 none(걸려들에 의해 연결된 예 반대) :big_ax.tick_params(labelcolor='none', top='off', bottom='off', left='off', right='off')
마리우스

2
AttributeError: 'numpy.ndarray' object has no attribute 'set_xlabel'문에 오류가 ax.set_xlabel('Common x-label')있습니다. 알아낼 수 있습니까?
hengxin

5

왼쪽 하단에서 서브 플롯에 보이지 않는 레이블을 만들어 공통 레이블을위한 공간을 확보하면 더 나아질 것입니다. 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'])

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


1
보이지 않는 라벨을 잘 사용! 감사합니다
colelemonz

3

그래프 그리드를 그릴 때 비슷한 문제가 발생했습니다. 그래프는 두 부분 (상단 및 하단)으로 구성됩니다. y- 라벨은 두 부분의 중앙에 위치해야했습니다.

외부 그림의 위치를 ​​아는 것에 의존하는 솔루션을 사용하고 싶지 않았으므로 (figure.text ()와 같이) set_ylabel () 함수의 y 위치를 조작했습니다. 일반적으로 플롯의 중간에 0.5가 추가됩니다. 내 코드에서 부분 (hspace) 사이의 패딩이 0이므로 두 부분 중 중간 부분을 위쪽 부분을 기준으로 계산할 수 있습니다.

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()

그림

단점 :

  • 플롯까지의 수평 거리는 상단 부분을 기준으로하며 하단 눈금은 레이블로 확장 될 수 있습니다.

  • 공식은 부품 사이의 공간을 고려하지 않습니다.

  • 상단 부분의 높이가 0 인 경우 예외가 발생합니다.

그림 사이에 패딩을 고려한 일반적인 솔루션이있을 수 있습니다.


이봐, 나는 당신의 대답의 맥락에서 이것을 매우 많이 할 수있는 방법을 찾았지만이 문제들 중 일부를 해결할 수도 있습니다. stackoverflow.com/a/44020303/4970632 참조 (아래)
Luke Davis

2

최신 정보:

이 기능은 이제 최근에 pypi에서 릴리스 한 proplot matplotlib 패키지의 일부입니다 . 기본적으로 그림을 만들 때 레이블은 축간에 "공유"됩니다.


원래 답변 :

더 강력한 방법을 발견했습니다.

당신이 알고있는 경우 bottomtop에 갔다 kwargs로 GridSpec초기화하거나, 그렇지 않으면 당신의 축 가장자리 위치 알 Figure좌표를 , 당신은 또한에 ylabel 위치를 지정할 수 있습니다 Figure약간의 공상과 좌표를 마법을 "변환". 예를 들면 다음과 같습니다.

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!')

... 여전히 레이블 이 왼쪽과 오른쪽 으로 적절히 조정 되어 눈금 레이블 과 겹치지 않도록 정상과 마찬가지로 항상 원하는 서브 플로트 사이 에서 정확하게 조정됩니다 .

또한조차 사용하지 않으면 set_positionylabel은 기본적으로 그림의 절반에 정확하게 나타납니다 . 레이블이 마지막으로 그려 질 때 기본 좌표 변환이 변경되었는지 여부를 확인하지 않고-좌표에 matplotlib0.5를 사용 하기 때문 y입니다.

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