2011-08-05 93 views
102

標籤,我有以下情節:pyplot軸的次要情節

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軸標籤。儘管如此,我還是希望爲每個子區域創建不同的標題。

我嘗試了一些事情,但他們沒有工作權

回答

150

您可以創建一個大插曲覆蓋兩個次要情節,然後設置共同的標籤。

import random 
import matplotlib.pyplot as plt 

x = range(1, 101) 
y1 = [random.randint(1, 100) for _ in xrange(len(x))] 
y2 = [random.randint(1, 100) for _ in xrange(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='off', bottom='off', left='off', right='off') 

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) 

common_labels.png

的另一種方法是使用fig.text()直接設置共同的標籤的位置。

import random 
import matplotlib.pyplot as plt 

x = range(1, 101) 
y1 = [random.randint(1, 100) for _ in xrange(len(x))] 
y2 = [random.randint(1, 100) for _ in xrange(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) 

common_labels_text.png

+1

的suptitle功能使用fig.text()的版本。所以這可能是「官方」的方式呢? – PhML

+2

值得強調的是'ax'必須在'ax1'和'ax2'之前創建,否則大圖會掩蓋小圖。 –

+0

如果全局繪圖參數包含(可見)網格,則也需要ax.grid(False)或plt.grid(False)。 –

10

文衛廖的回答是好,如果你不嘗試導出矢量圖形,或者你已經設置了matplotlib後端忽視無色軸;否則隱藏的軸將出現在導出的圖形中。

我的回答suplabel這裏類似於使用fig.text功能的fig.suptitle。因此沒有斧頭藝術家被創造並且變得無色。 但是,如果您嘗試多次撥打電話,則會將文本添加到對方的頂部(因爲fig.suptitle也會這樣做)。廖文偉的答案不是,因爲fig.add_subplot(111)將返回相同的軸對象,如果它已經創建。

我的函數也可以在繪圖創建後調用。使用subplots

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

一個簡單的方法:

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='off', bottom='off', left='off', right='off') 
plt.grid(False) 
plt.xlabel("common X") 
plt.ylabel("common Y") 
+0

完美的短! – maggie

+1

這應該是公認的答案 – kungfujam

+0

我同意這是一個很好的答案 –

7

這裏是你設置的曲線中的一個的ylabel,所以它垂直居中調節它的位置的解決方案。這樣你可以避免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.)') 

enter image description here