अन्य उत्तरों में विधियाँ ठीक से काम नहीं करेंगी जब yticks बड़े होंगे। यालेबेल या तो टिक्स के साथ ओवरलैप करेगा, आंकड़े के बाईं या पूरी तरह से अदृश्य / बाहर क्लिप किया जाएगा।
मैंने Hagne के उत्तर को संशोधित किया है, इसलिए यह xlabel और ylabel दोनों के लिए सबप्लॉट के 1 से अधिक कॉलम के साथ काम करता है, और यह चित्र में दिखाई दे रहे ylabel को रखने के लिए कथानक को बदलता है।
def set_shared_ylabel(a, xlabel, ylabel, labelpad = 0.01, figleftpad=0.05):
"""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,0].get_figure()
f.canvas.draw() #sets f.canvas.renderer needed below
# get the center position for all plots
top = a[0,0].get_position().y1
bottom = a[-1,-1].get_position().y0
# get the coordinates of the left side of the tick labels
x0 = 1
x1 = 1
for at_row in a:
at = at_row[0]
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
x1 = bboxes.x1
tick_label_left = x0
# shrink plot on left to prevent ylabel clipping
# (x1 - tick_label_left) is the x coordinate of right end of tick label,
# basically how much padding is needed to fit tick labels in the figure
# figleftpad is additional padding to fit the ylabel
plt.subplots_adjust(left=(x1 - tick_label_left) + figleftpad)
# set position of label,
# note that (figleftpad-labelpad) refers to the middle of the ylabel
a[-1,-1].set_ylabel(ylabel)
a[-1,-1].yaxis.set_label_coords(figleftpad-labelpad,(bottom + top)/2, transform=f.transFigure)
# set xlabel
y0 = 1
for at in axes[-1]:
at.set_xlabel('') # just to make sure we don't and up with multiple labels
bboxes, _ = at.xaxis.get_ticklabel_extents(fig.canvas.renderer)
bboxes = bboxes.inverse_transformed(fig.transFigure)
yt = bboxes.y0
if yt < y0:
y0 = yt
tick_label_bottom = y0
axes[-1, -1].set_xlabel(xlabel)
axes[-1, -1].xaxis.set_label_coords((left + right) / 2, tick_label_bottom - labelpad, transform=fig.transFigure)
यह निम्नलिखित उदाहरण के लिए काम करता है, जबकि हगेन का उत्तर यलैबेल (क्योंकि यह कैनवास के बाहर है) और केवाईसी के यलैबेल टिक लेबल के साथ ओवरलैप नहीं करेगा:
import matplotlib.pyplot as plt
import itertools
fig, axes = plt.subplots(3, 4, sharey='row', sharex=True, squeeze=False)
fig.subplots_adjust(hspace=.5)
for i, a in enumerate(itertools.chain(*axes)):
a.plot([0,4**i], [0,4**i])
a.set_title(i)
set_shared_ylabel(axes, 'common X', 'common Y')
plt.show()
वैकल्पिक रूप से, यदि आप बेरंग अक्ष के साथ ठीक हैं, तो मैंने जूलियन चेन के समाधान को संशोधित किया है ताकि ylabel टिक लेबल के साथ ओवरलैप न हो।
असल में, हमें बस बेरंग के यिलर्स को सेट करना है, इसलिए यह सबप्लाट्स के सबसे बड़े यिलर्स से मेल खाता है इसलिए बेरंग टिक लेबल यलबेल के लिए सही स्थान सेट करता है।
फिर से, हमें कतरन को रोकने के लिए साजिश को सिकोड़ना होगा। यहां मैंने हार्ड को सिकोड़ने के लिए राशि कोडित की है, लेकिन आप एक संख्या खोजने के लिए चारों ओर खेल सकते हैं जो आपके लिए काम करता है या ऊपर की विधि की तरह गणना करता है।
import matplotlib.pyplot as plt
import itertools
fig, axes = plt.subplots(3, 4, sharey='row', sharex=True, squeeze=False)
fig.subplots_adjust(hspace=.5)
miny = maxy = 0
for i, a in enumerate(itertools.chain(*axes)):
a.plot([0,4**i], [0,4**i])
a.set_title(i)
miny = min(miny, a.get_ylim()[0])
maxy = max(maxy, a.get_ylim()[1])
# add a big axes, hide frame
# set ylim to match the largest range of any subplot
ax_invis = fig.add_subplot(111, frameon=False)
ax_invis.set_ylim([miny, maxy])
# hide tick and tick label of the big axis
plt.tick_params(labelcolor='none', top=False, bottom=False, left=False, right=False)
plt.xlabel("common X")
plt.ylabel("common Y")
# shrink plot to prevent clipping
plt.subplots_adjust(left=0.15)
plt.show()