하위 그림의 공통 축 레이블 설정 방법
저는 다음과 같은 줄거리를 가지고 있습니다.
import matplotlib.pyplot as plt
fig2 = plt.figure()
ax3 = fig2.add_subplot(2,1,1)
ax4 = fig2.add_subplot(2,1,2)
ax4.loglog(x1, y1)
ax3.loglog(x2, y2)
ax3.set_ylabel('hello')
두 하위 플롯 각각에 대한 축 레이블과 제목뿐만 아니라 두 하위 플롯에 걸쳐 있는 공통 레이블도 만들 수 있기를 원합니다.예를 들어, 두 그림의 축이 모두 동일하기 때문에 x 및 y 축 레이블 세트가 하나만 필요합니다.하위 플롯마다 다른 제목을 원합니다.
몇 가지를 시도해 보았지만 제대로 작동하지 않았습니다.
두 개의 하위 그림을 포함하는 큰 하위 그림을 만든 다음 공통 레이블을 설정할 수 있습니다.
import random
import matplotlib.pyplot as plt
x = range(1, 101)
y1 = [random.randint(1, 100) for _ in range(len(x))]
y2 = [random.randint(1, 100) for _ in range(len(x))]
fig = plt.figure()
ax = fig.add_subplot(111) # The big subplot
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
# Turn off axis lines and ticks of the big subplot
ax.spines['top'].set_color('none')
ax.spines['bottom'].set_color('none')
ax.spines['left'].set_color('none')
ax.spines['right'].set_color('none')
ax.tick_params(labelcolor='w', top=False, bottom=False, left=False, right=False)
ax1.loglog(x, y1)
ax2.loglog(x, y2)
# Set common labels
ax.set_xlabel('common xlabel')
ax.set_ylabel('common ylabel')
ax1.set_title('ax1 title')
ax2.set_title('ax2 title')
plt.savefig('common_labels.png', dpi=300)
또 다른 방법은 fig.text()를 사용하여 공통 레이블의 위치를 직접 설정하는 것입니다.
import random
import matplotlib.pyplot as plt
x = range(1, 101)
y1 = [random.randint(1, 100) for _ in range(len(x))]
y2 = [random.randint(1, 100) for _ in range(len(x))]
fig = plt.figure()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
ax1.loglog(x, y1)
ax2.loglog(x, y2)
# Set common labels
fig.text(0.5, 0.04, 'common xlabel', ha='center', va='center')
fig.text(0.06, 0.5, 'common ylabel', ha='center', va='center', rotation='vertical')
ax1.set_title('ax1 title')
ax2.set_title('ax2 title')
plt.savefig('common_labels_text.png', dpi=300)
한 가지 간단한 사용 방법subplots
:
import matplotlib.pyplot as plt
fig, axes = plt.subplots(3, 4, sharex=True, sharey=True)
# add a big axes, hide frame
fig.add_subplot(111, frameon=False)
# hide tick and tick label of the big axes
plt.tick_params(labelcolor='none', top=False, bottom=False, left=False, right=False)
plt.grid(False)
plt.xlabel("common X")
plt.ylabel("common Y")
새로운 정보 표시 lib 3.4.0
이제 공통 축 레이블을 설정하는 기본 제공 방법이 있습니다.
작업을 재현하는 방법loglog
그림(공통 레이블이지만 별도의 제목):
x = np.arange(0.01, 10.01, 0.01)
y = 2 ** x
fig, (ax1, ax2) = plt.subplots(2, 1, constrained_layout=True)
ax1.loglog(y, x)
ax2.loglog(x, y)
# separate subplot titles
ax1.set_title('ax1.title')
ax2.set_title('ax2.title')
# common axis labels
fig.supxlabel('fig.supxlabel')
fig.supylabel('fig.supylabel')
plt.setp()
작업을 수행합니다.
# plot something
fig, axs = plt.subplots(3,3, figsize=(15, 8), sharex=True, sharey=True)
for i, ax in enumerate(axs.flat):
ax.scatter(*np.random.normal(size=(2,200)))
ax.set_title(f'Title {i}')
# set labels
plt.setp(axs[-1, :], xlabel='x axis label')
plt.setp(axs[:, 0], ylabel='y axis label')
벡터 그래픽을 내보내려고 하지 않거나 색이 없는 축을 무시하도록 matplotlib 백엔드를 설정한 경우 랴오원웨이의 답변이 좋습니다. 그렇지 않으면 내보낸 그래픽에 숨겨진 축이 표시됩니다.
나의 대답suplabel
여기는 그것과 유사합니다.fig.suptitle
를 사용하는fig.text
기능.따라서 도끼 예술가는 창조되고 무색으로 만들어지지 않습니다.그러나 여러 번 호출하려고 하면 텍스트가 서로 추가됩니다.fig.suptitle
역시 그렇다).랴오원웨이의 대답은 그렇지 않습니다, 왜냐하면fig.add_subplot(111)
이미 생성된 경우 동일한 Axes 개체를 반환합니다.
내 함수는 플롯이 생성된 후에도 호출될 수 있습니다.
def suplabel(axis,label,label_prop=None,
labelpad=5,
ha='center',va='center'):
''' Add super ylabel or xlabel to the figure
Similar to matplotlib.suptitle
axis - string: "x" or "y"
label - string
label_prop - keyword dictionary for Text
labelpad - padding from the axis (default: 5)
ha - horizontal alignment (default: "center")
va - vertical alignment (default: "center")
'''
fig = pylab.gcf()
xmin = []
ymin = []
for ax in fig.axes:
xmin.append(ax.get_position().xmin)
ymin.append(ax.get_position().ymin)
xmin,ymin = min(xmin),min(ymin)
dpi = fig.dpi
if axis.lower() == "y":
rotation=90.
x = xmin-float(labelpad)/dpi
y = 0.5
elif axis.lower() == 'x':
rotation = 0.
x = 0.5
y = ymin - float(labelpad)/dpi
else:
raise Exception("Unexpected axis: x or y")
if label_prop is None:
label_prop = dict()
pylab.text(x,y,label,rotation=rotation,
transform=fig.transFigure,
ha=ha,va=va,
**label_prop)
다음 솔루션에서는 그림 중 하나의 y 레이블을 설정하고 그래프의 위치를 수직으로 중앙에 오도록 조정할 수 있습니다.이렇게 하면 KYC에서 언급한 문제를 피할 수 있습니다.
import numpy as np
import matplotlib.pyplot as plt
def set_shared_ylabel(a, ylabel, labelpad = 0.01):
"""Set a y label shared by multiple axes
Parameters
----------
a: list of axes
ylabel: string
labelpad: float
Sets the padding between ticklabels and axis label"""
f = a[0].get_figure()
f.canvas.draw() #sets f.canvas.renderer needed below
# get the center position for all plots
top = a[0].get_position().y1
bottom = a[-1].get_position().y0
# get the coordinates of the left side of the tick labels
x0 = 1
for at in a:
at.set_ylabel('') # just to make sure we don't and up with multiple labels
bboxes, _ = at.yaxis.get_ticklabel_extents(f.canvas.renderer)
bboxes = bboxes.inverse_transformed(f.transFigure)
xt = bboxes.x0
if xt < x0:
x0 = xt
tick_label_left = x0
# set position of label
a[-1].set_ylabel(ylabel)
a[-1].yaxis.set_label_coords(tick_label_left - labelpad,(bottom + top)/2, transform=f.transFigure)
length = 100
x = np.linspace(0,100, length)
y1 = np.random.random(length) * 1000
y2 = np.random.random(length)
f,a = plt.subplots(2, sharex=True, gridspec_kw={'hspace':0})
a[0].plot(x, y1)
a[1].plot(x, y2)
set_shared_ylabel(a, 'shared y label (a. u.)')
# list loss and acc are your data
fig = plt.figure()
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
ax1.plot(iteration1, loss)
ax2.plot(iteration2, acc)
ax1.set_title('Training Loss')
ax2.set_title('Training Accuracy')
ax1.set_xlabel('Iteration')
ax1.set_ylabel('Loss')
ax2.set_xlabel('Iteration')
ax2.set_ylabel('Accuracy')
yticks가 크면 다른 답변의 메서드가 제대로 작동하지 않습니다.y 레이블은 눈금과 겹치거나 왼쪽에서 잘리거나 그림 밖에서 완전히 보이지 않거나 표시되지 않습니다.
Hagne의 답변을 수정하여 xlabel과 ylabel 모두에 대해 1개 이상의 하위 플롯 열에서 작동하고 그림에서 ylabel이 보이도록 플롯을 이동합니다.
def set_shared_ylabel(a, xlabel, ylabel, labelpad = 0.01, figleftpad=0.05):
"""Set a y label shared by multiple axes
Parameters
----------
a: list of axes
ylabel: string
labelpad: float
Sets the padding between ticklabels and axis label"""
f = a[0,0].get_figure()
f.canvas.draw() #sets f.canvas.renderer needed below
# get the center position for all plots
top = a[0,0].get_position().y1
bottom = a[-1,-1].get_position().y0
# get the coordinates of the left side of the tick labels
x0 = 1
x1 = 1
for at_row in a:
at = at_row[0]
at.set_ylabel('') # just to make sure we don't and up with multiple labels
bboxes, _ = at.yaxis.get_ticklabel_extents(f.canvas.renderer)
bboxes = bboxes.inverse_transformed(f.transFigure)
xt = bboxes.x0
if xt < x0:
x0 = xt
x1 = bboxes.x1
tick_label_left = x0
# shrink plot on left to prevent ylabel clipping
# (x1 - tick_label_left) is the x coordinate of right end of tick label,
# basically how much padding is needed to fit tick labels in the figure
# figleftpad is additional padding to fit the ylabel
plt.subplots_adjust(left=(x1 - tick_label_left) + figleftpad)
# set position of label,
# note that (figleftpad-labelpad) refers to the middle of the ylabel
a[-1,-1].set_ylabel(ylabel)
a[-1,-1].yaxis.set_label_coords(figleftpad-labelpad,(bottom + top)/2, transform=f.transFigure)
# set xlabel
y0 = 1
for at in axes[-1]:
at.set_xlabel('') # just to make sure we don't and up with multiple labels
bboxes, _ = at.xaxis.get_ticklabel_extents(fig.canvas.renderer)
bboxes = bboxes.inverse_transformed(fig.transFigure)
yt = bboxes.y0
if yt < y0:
y0 = yt
tick_label_bottom = y0
axes[-1, -1].set_xlabel(xlabel)
axes[-1, -1].xaxis.set_label_coords((left + right) / 2, tick_label_bottom - labelpad, transform=fig.transFigure)
Hagne의 답변은 캔버스 밖에 있으므로 drawy label을 그릴 수 없으며 KYC의 y label은 눈금 레이블과 겹칩니다.
import matplotlib.pyplot as plt
import itertools
fig, axes = plt.subplots(3, 4, sharey='row', sharex=True, squeeze=False)
fig.subplots_adjust(hspace=.5)
for i, a in enumerate(itertools.chain(*axes)):
a.plot([0,4**i], [0,4**i])
a.set_title(i)
set_shared_ylabel(axes, 'common X', 'common Y')
plt.show()
또는 무채색 축에 문제가 없다면 Julian Chen의 솔루션을 수정하여 눈금 레이블과 겹치지 않도록 하였습니다.
기본적으로 무색의 임을 설정하여 하위 플롯의 가장 큰 임과 일치하도록 하면 무색의 눈금 레이블이 y 레이블의 정확한 위치를 설정할 수 있습니다.
다시 말하지만, 우리는 클리핑을 방지하기 위해 플롯을 축소해야 합니다.여기서 축소할 양을 하드 코딩했지만, 여러분은 자신에게 맞는 숫자를 찾거나 위의 방법처럼 계산할 수 있습니다.
import matplotlib.pyplot as plt
import itertools
fig, axes = plt.subplots(3, 4, sharey='row', sharex=True, squeeze=False)
fig.subplots_adjust(hspace=.5)
miny = maxy = 0
for i, a in enumerate(itertools.chain(*axes)):
a.plot([0,4**i], [0,4**i])
a.set_title(i)
miny = min(miny, a.get_ylim()[0])
maxy = max(maxy, a.get_ylim()[1])
# add a big axes, hide frame
# set ylim to match the largest range of any subplot
ax_invis = fig.add_subplot(111, frameon=False)
ax_invis.set_ylim([miny, maxy])
# 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")
# shrink plot to prevent clipping
plt.subplots_adjust(left=0.15)
plt.show()
다음과 같이 축에 "set"를 사용할 수 있습니다.
axes[0].set(xlabel="KartalOl", ylabel="Labeled")
언급URL : https://stackoverflow.com/questions/6963035/how-to-set-common-axes-labels-for-subplots
'programing' 카테고리의 다른 글
Git GUI 또는 ssh-keygen을 사용하는 SSH 개인 키 사용 권한이 너무 열려 있음 (0) | 2023.06.25 |
---|---|
Oracle이 최근 1시간 내에 업데이트된 레코드 가져오기 (0) | 2023.06.25 |
Spring Data MongoDB에서 쿼리에 대한 특정 필드만 반환하는 방법은 무엇입니까? (0) | 2023.06.25 |
앱이 앱스토어에 없는 경우 Firebase Dynamic Links를 테스트하려면 어떻게 해야 합니까? (0) | 2023.06.25 |
VBA에서 셀 또는 범위만 재계산할 수 있습니까? (0) | 2023.06.25 |