2013-10-09 35 views
16

Trong ô dưới đây tôi có hai ô phân tán có thang số khác nhau, vì vậy nhãn trục Y không được căn chỉnh. Có cách nào tôi có thể buộc sự liên kết ngang trong các nhãn trục y?matplotlib: Căn chỉnh nhãn trục y trong ô xếp chồng xếp chồng lên nhau

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

những gì bạn muốn được mô tả ở đây: http://matplotlib.org/faq/howto_faq.html # align-my-ylabels-over-nhiều-subplots –

Trả lời

18

Bạn có thể sử dụng phương pháp 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

cảm ơn bạn! Tôi đã cố gắng làm một cái gì đó dọc theo dòng "ax.get_yaxis(). Get_label(). Set_ha ('left')" nhưng nó không hoạt động. Tôi đoán tôi đã không hoàn toàn hiểu cách sắp xếp nhãn hiệu. – dimka

+3

Có cách nào để * tự động * xác định khoảng cách tối thiểu có thể chấp nhận được từ các nhãn đánh dấu trên cả hai trục không? I E. để tìm ra vị trí tự động độc lập nào, sau đó thiết lập rõ ràng tất cả các vị trí đó bằng với vị trí lớn nhất? – andybuckley

+3

@andybuckley, tôi chỉ chơi xung quanh với tự động căn chỉnh các nhãn. Bạn có thể nhận được các giá trị tối thiểu/tối đa của các vị trí bằng cách sử dụng 'ax.yaxis.label.get_position()', nhưng không gian tọa độ không giống với những gì được sử dụng trong 'ax.yaxis.set_label_coords()' - bạn có để sử dụng 'ax.yaxis.label.set_position()' và một chút của một hack: 'ax.yaxis._autolabelpos = False' hoặc người nào khác nó reset vị trí khi bạn gọi' draw() ' –

2

Như đăng trong bình luận, những gì bạn đang tìm kiếm được giải quyết bằng set_label_coords() như described here. Trong trường hợp của bạn, nó sẽ giống như sau:

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

Đây là hàm tôi đã viết để tự động căn chỉnh nhãn, nhưng dường như nó không hoạt động trong tập lệnh, chỉ tương tác.

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) 

Và một ví dụ:

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

tôi cung cấp một giải pháp cuối cùng, nhưng trước tiên tôi nói với cách mà không dẫn đến thành công.

Tôi đã xem lại vấn đề này gần đây và dành nhiều thời gian để thử các giải pháp khác nhau, tức là cố gắng gần như tất cả các kết hợp chuyển đổi giữa các hệ tọa độ khác nhau và mối quan hệ của chúng với tight_layout(). Tôi đã thử nghiệm chỉ với backend_pdf, vì vậy tôi không thể nói về phương tiện tương tác. Nhưng một thời gian ngắn, kết luận của tôi là không có vấn đề làm thế nào bạn cố gắng tìm ra các vị trí và cố gắng biến đổi chúng, không thể ở cấp độ này để căn chỉnh các nhãn trục. Tôi đoán bằng cách nào đó nó sẽ là có thể, ví dụ bằng cách nào đó trong nội bộ matplotlib có thể sắp xếp các trục của các subplots mình. Chỉ với vẽ vào file pdf hai lần và làm một cái gì đó như dưới đây Inbetween, tôi có thể đạt được vị trí tốt hơn, nhưng vẫn không thẳng hàng:

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

Đó là một sự xấu hổ như một chức năng cơ bản không thể đạt được, và nó là che khuất cách các không gian tọa độ khác nhau được chuyển đổi và thay đổi kích thước ở các bước khác nhau của âm mưu. Tôi sẽ đánh giá cao rất nhiều để xem một lời giải thích rõ ràng về điều này, bởi vì các matplotlib webpage chỉ phác thảo kiến ​​trúc, trình bày các trường hợp đơn giản, nhưng không giải thích các tình huống như thế này. Ngoài ra tôi ngạc nhiên rằng phương pháp chấp nhận hoặc trả lại tọa độ không nói trong docstring của họ những loại tọa độ là những người. Cuối cùng tôi thấy rất hữu ích this tutorial.

Giải pháp

Cuối cùng, thay vì can thiệp vào biến đổi, tôi tạo ra trong GridSpec hàng bổ sung của zero chiều cao và trục vô hình (tương tự có thể được thực hiện với một cột chiều rộng bằng không đối với nhãn trục y). Sau đó, tôi đã thêm nhãn cho các ô con này, đặt verticalalignment thành 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') 
Các vấn đề liên quan