2013-10-09 328 views
16

在下圖中,我有兩個散點圖,它們有不同的數字刻度,所以它們的Y軸標籤沒有對齊。有什麼辦法可以強制y軸標籤中的水平對齊?matplotlib:在堆積的散點圖中對齊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() 

stacked scatter plots

+0

你想要的是在這裏描述:http://matplotlib.org/faq/howto_faq。html#align-my-ylabels-跨多個子圖 –

回答

18

可以使用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) 

enter image description here

+0

謝謝!我試圖按照「ax.get_yaxis()。get_label()。set_ha('left')」的方法做一些事情,但沒有奏效。我想我並沒有完全理解標籤對齊如何工作。 – dimka

+3

有沒有辦法*自動*確定兩個軸上刻度線標籤的最小可接受距離是多少?即找到獨立的自動倉位是什麼,然後明確地將它們全部設置爲最大? – andybuckley

+3

@andybuckley,我只是玩弄自動對齊標籤。您可以使用'ax.yaxis.label.get_position()'獲得位置的最小/最大值,但座標空間與'ax.yaxis.set_label_coords()'中使用的座標空間不同。使用'ax.yaxis.label.set_position()'和一點黑客:'ax.yaxis._autolabelpos = False',否則當你調用'draw()'時重置位置。 –

2

張貼在評論,你要尋找一個使用set_label_coords()作爲described here解決。對於你的情況下,它會是這樣的:

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

這裏是我已經寫了自動對準標籤的功能,但它似乎並不在一個腳本工作,只有交互。

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

example figure

0

我在最後提供一個解決方案,但首先我告訴它的方式不會導致成功。

我最近重新審視這個問題,並花了相當長的一段時間,嘗試不同的解決方案,即試圖幾乎所有的轉換可能的組合之間的不同座標系,以及它們與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 webpage只概述了架構,提供了簡單的案例,但未能解釋這樣的情況。另外我感到驚訝的是,接受或返回座標的方法並沒有在它們的文檔字符串中告訴它們是什麼類型的座標。最後我發現非常有用this tutorial

在結束時,而不是與變換搞亂,我在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')