2011-08-05 10 views
102

के लिए लेबल अक्ष मैं निम्नलिखित साजिश है:pyplot subplots

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

मैं सिर्फ दो subplots से प्रत्येक के लिए नहीं कुल्हाड़ियों लेबल और खिताब बनाने के लिए सक्षम होना चाहते हैं, लेकिन यह भी आम लेबल है कि दोनों subplots फैली होती हैं। उदाहरण के लिए, चूंकि दोनों भूखंडों में समान अक्ष हैं, इसलिए मुझे केवल एक्स और वाई-अक्ष लेबल के एक सेट की आवश्यकता है। हालांकि मैं प्रत्येक सबप्लॉट के लिए अलग-अलग खिताब चाहता हूं।

मैं कुछ चीजें करने की कोशिश की, लेकिन उनमें से कोई भी काम सही

उत्तर

150

आप एक बड़ा subplot कि दो subplots को शामिल किया गया और उसके बाद आम लेबल सेट बना सकते हैं।

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'' और 'ax2' से पहले' ax' बनाया जाना है, अन्यथा बड़ी साजिश छोटे भूखंडों को कवर करेगी। वैश्विक प्लॉटिंग पैरामीटर में एक (दृश्यमान) ग्रिड शामिल होने पर –

+0

ax.grid (गलत) या plt.grid (झूठी) भी आवश्यक है। –

10

वेन-वेई लियाओ का जवाब अच्छा है अगर आप वेक्टर ग्राफिक्स निर्यात करने के लिए या कि आप बेरंग कुल्हाड़ियों की अनदेखी करने के लिए अपने matplotlib बैकेंड की स्थापना की है कोशिश नहीं कर रहे हैं; अन्यथा छुपा अक्ष निर्यातित ग्राफिक में दिखाई देगी।

मेरा उत्तर suplabel यहां fig.suptitle जैसा है जो fig.text फ़ंक्शन का उपयोग करता है। इसलिए कोई कुल्हाड़ी कलाकार नहीं बनाया गया है और रंगहीन बना दिया गया है। हालांकि, यदि आप इसे कई बार कॉल करने का प्रयास करते हैं तो आपको एक दूसरे के शीर्ष पर टेक्स्ट जोड़ा जाएगा (जैसा कि fig.suptitle भी करता है)। वेन-वेई लियो का जवाब नहीं है, क्योंकि fig.add_subplot(111) उसी एक्सिस ऑब्जेक्ट को वापस कर देगा यदि यह पहले से बनाया गया है।

भूखंडों के निर्माण के बाद भी मेरे कार्य को बुलाया जा सकता है।

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

एक साधारण 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='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 सेट और इसलिए यह ऊर्ध्व रूप से केंद्रित है इसके बारे में स्थिति को समायोजित है। इस तरह आप केवाईसी द्वारा उल्लिखित समस्याओं से बचें।

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

संबंधित मुद्दे