[英]matplotlib: Aligning y-axis labels in stacked scatter plots
在下圖中我有兩個散點圖,它們具有不同的數字刻度,因此它們的Y軸標簽沒有對齊。 有什么辦法可以在y軸標簽上強制水平對齊嗎?
import matplotlib.pylab as plt
import random
import matplotlib.gridspec as gridspec
random.seed(20)
data1 = [random.random() for i in range(10)]
data2 = [random.random()*1000 for i in range(10)]
gs = gridspec.GridSpec(2,1)
fig = plt.figure()
ax = fig.add_subplot(gs[0])
ax.plot(data1)
ax.set_ylabel(r'Label One', size =16)
ax = fig.add_subplot(gs[1])
ax.plot(data2)
ax.set_ylabel(r'Label Two', size =16)
plt.show()
您可以使用set_label_coords方法。
import matplotlib.pylab as plt
import random
import matplotlib.gridspec as gridspec
random.seed(20)
data1 = [random.random() for i in range(10)]
data2 = [random.random()*1000 for i in range(10)]
gs = gridspec.GridSpec(2,1)
fig = plt.figure()
ax = fig.add_subplot(gs[0])
ax.plot(data1)
ax.set_ylabel(r'Label One', size =16)
ax.get_yaxis().set_label_coords(-0.1,0.5)
ax = fig.add_subplot(gs[1])
ax.plot(data2)
ax.set_ylabel(r'Label Two', size =16)
ax.get_yaxis().set_label_coords(-0.1,0.5)
自編寫此問題以來,matplotlib添加了一個易於使用的功能,可以對齊標簽。 強制對齊標簽的正確方法是在顯示圖形之前使用函數fig.align_labels()
。
如果需要更精細的粒度控制,還可以使用函數Figure.align_xlabels()
或Figure.align_ylabels()
。
這是問題中發布的代碼的工作版本。 只添加了一行(第二行到最后一行)來制定解決方案。
import matplotlib.pylab as plt
import random
import matplotlib.gridspec as gridspec
random.seed(20)
data1 = [random.random() for i in range(10)]
data2 = [random.random()*1000 for i in range(10)]
gs = gridspec.GridSpec(2,1)
fig = plt.figure()
ax = fig.add_subplot(gs[0])
ax.plot(data1)
ax.set_ylabel(r'Label One', size =16)
ax = fig.add_subplot(gs[1])
ax.plot(data2)
ax.set_ylabel(r'Label Two', size =16)
fig.align_labels()
plt.show()
有關更多信息,請參閱有關對齊標簽的Matplotlib文檔 。
正如在評論中發布的那樣,您正在尋找的是使用此處所述的 set_label_coords()
來解決的。 對於你的情況,它將是這樣的:
labelx = -0.5
ax = fig.add_subplot(gs[0])
ax.plot(data1)
ax.set_ylabel(r'Label One', size=16)
ax.yaxis.set_label_coords(labelx, 0.5)
ax = fig.add_subplot(gs[1])
ax.plot(data2)
ax.set_ylabel(r'Label Two', size=16)
ax.yaxis.set_label_coords(labelx, 0.5)
這是我為自動對齊標簽而編寫的一個函數,但它似乎不能在腳本中工作,只能以交互方式工作。
def align_labels(axes_list,axis='y',align=None):
if align is None:
align = 'l' if axis == 'y' else 'b'
yx,xy = [],[]
for ax in axes_list:
yx.append(ax.yaxis.label.get_position()[0])
xy.append(ax.xaxis.label.get_position()[1])
if axis == 'x':
if align in ('t','top'):
lim = max(xy)
elif align in ('b','bottom'):
lim = min(xy)
else:
if align in ('l','left'):
lim = min(yx)
elif align in ('r','right'):
lim = max(yx)
if align in ('t','b','top','bottom'):
for ax in axes_list:
t = ax.xaxis.label.get_transform()
x,y = ax.xaxis.label.get_position()
ax.xaxis.set_label_coords(x,lim,t)
else:
for ax in axes_list:
t = ax.yaxis.label.get_transform()
x,y = ax.yaxis.label.get_position()
ax.yaxis.set_label_coords(lim,y,t)
一個例子:
fig,ax = subplots(2,2)
ax00,ax01 = ax[0]
ax10,ax11 = ax[1]
ax00.set_ylim(1000,5000)
ax00.set_ylabel('top')
ax10.set_ylabel('bottom')
ax10.set_xlabel('left')
ax11.set_xlabel('right')
ax11.xaxis.axis_date()
fig.autofmt_xdate()
#we have to call draw() so that matplotlib will figure out the automatic positions
fig.canvas.draw()
align_labels(ax[:,0],'y')
align_labels(ax[1],'x')
我最后提供了一個解決方案,但首先我告訴哪種方式不會帶來成功。
我最近重新審視了這個問題,並花了很長時間嘗試各種解決方案,即嘗試幾乎所有可能的不同坐標系之間的轉換組合,以及它們與tight_layout()
的關系。 我只用backend_pdf
實驗,所以我無法講述交互式媒體。 但簡而言之,我的結論是,無論您如何嘗試找出位置並嘗試對其進行轉換,在此級別上都無法對齊軸標簽。 我想它應該是可能的,例如某種程度上matplotlib內部能夠對齊子圖本身的軸。 只有兩次繪制到pdf文件並執行類似下面的內容,我才能獲得更好的位置,但仍然沒有對齊:
# sorry for the `self`, this is from a class
def align_x_labels(self):
self.lowest_ax = min(self.axes.values(),
key = lambda ax: ax.xaxis.label.get_position()[1])
self.lowest_xlab_dcoo = self.lowest_ax.transData.transform(
self.lowest_ax.xaxis.label.get_position())
list(
map(
lambda ax: \
ax.xaxis.set_label_coords(
self.fig.transFigure.inverted().transform(
ax.transAxes.transform((0.5, 0.5)))[0],
self.fig.transFigure.inverted().transform(
self.lowest_xlab_dcoo)[1],
transform = self.fig.transFigure
),
self.axes.values()
)
)
令人遺憾的是,無法實現這樣的基本功能,並且在不同的繪圖步驟中如何變換和重新縮放不同的坐標空間是模糊的。 我非常感謝看到對此的明確解釋,因為matplotlib網頁僅概述了體系結構,提供了簡單的案例,但未能解釋這樣的情況。 另外,我很驚訝接受或返回坐標的方法並沒有告訴他們的文檔字符串是什么類型的坐標。 最后我發現本教程非常有用。
解
最后,我沒有弄亂變換,而是在GridSpec
創建了一個零高度和不可見軸的附加行(對於y軸標簽,可以使用零寬度列完成相同的行)。 然后我為這些子圖添加了標簽,將verticalalignment
設置為top
。
# get one of the zero height phantom subplots to `self.ax`:
self.get_subplot(i, 1)
# set empty ticklabels:
self.ax.xaxis.set_ticklabels([])
self.ax.yaxis.set_ticklabels([])
# set the axis label:
self.ax.set_xlabel(labtext, fontproperties = self.fp_axis_lab)
# and this is matter of aesthetics
# sometimes bottom or center might look better:
self.ax.xaxis.label.set_verticalalignment('top')
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.