সাবপ্লটগুলির জন্য পাইপ্লট অক্ষের লেবেল


186

আমার নিম্নলিখিত প্লট রয়েছে:

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- অক্ষ লেবেলের একটি সেট প্রয়োজন। যদিও আমি প্রতিটি সাবপ্লোটের জন্য আলাদা আলাদা শিরোনাম চাই।

আমি কয়েকটি জিনিস চেষ্টা করেছিলাম কিন্তু তাদের মধ্যে কেউই সঠিক কাজ করেনি

উত্তর:


259

আপনি একটি বৃহত সাবপ্লট তৈরি করতে পারেন যা দুটি সাবপ্লটকে কভার করে এবং তারপরে সাধারণ লেবেল সেট করে।

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=False, bottom=False, left=False, right=False)

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
সাবটাইটেল ফাংশনটি fig.text () সংস্করণ ব্যবহার করে। সুতরাং এটি হতে পারে এটি "অফিসিয়াল" উপায়?
পিএমএল

4
এটির উপর জোর axদেওয়ার দরকার যা আগে তৈরি করতে হয়েছিল ax1এবং ax2অন্যথায় বড় প্লটটি ছোট প্লটগুলি upেকে দেবে।
1 ''

ax.grid (মিথ্যা) বা plt.grid (মিথ্যা) এছাড়াও প্রয়োজনীয় যদি বিশ্বব্যাপী ষড়যন্ত্র পরামিতিগুলিতে একটি (দৃশ্যমান) গ্রিড অন্তর্ভুক্ত থাকে।
নরেন

3
দেখে মনে হচ্ছে ম্যাটপ্লটপ্লিবের সাম্প্রতিক সংস্করণগুলির সাথে প্রথম পন্থাটি আর কাজ করে না (আমি ২.০.২ ব্যবহার করি): এনকোলেসিং কুড়ালে যুক্ত লেবেলগুলি দৃশ্যমান নয়।
এম তোয়া

প্রতিটি পৃথক সাবপ্লোটে কীভাবে y_label যুক্ত করবেন?
ফারদিন

115

একটি সহজ উপায় 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")

1
ax.grid (মিথ্যা) বা plt.grid (মিথ্যা) এছাড়াও প্রয়োজনীয় যদি বিশ্বব্যাপী ষড়যন্ত্র পরামিতিগুলিতে একটি (দৃশ্যমান) গ্রিড অন্তর্ভুক্ত থাকে।
নরেন

1
আমি এটি একটি (5, 1) সাবপ্লট এর জন্য করছি এবং আমার ইয়েলবেল সাবপ্লটগুলির কাছে না গিয়ে উইন্ডোটির বাম প্রান্তে বন্ধ।
এভিড্লো

1
আপনি একটি upvote পেয়েছেন। তবে দয়া করে কোডটি কী করছে তা সর্বদা ব্যাখ্যা করুন, একটি চিত্র সংযুক্ত করুন বা একটি উদাহরণ দেখান, কারণ এটি পেতে অবশ্যই এটি কিছুটা সময় নিয়েছিল।
করিম জিরোদি

4
পরিবর্তন 'off'করার জন্য FalseMatplotlib এর নতুন সংস্করণের সাথে (আমি 2.2.2 আছে)
টেড

2
এবং তারপরে আপনি প্লটগুলি কীভাবে যুক্ত করবেন? for ax in axes: ax.plot(x, y)কোন ভাল কাজ বলে মনে হচ্ছে না।
ব্যবহারকারী সংখ্যা

16

যদি আপনি ভেক্টর গ্রাফিক্স রফতানি করার চেষ্টা না করেন বা বর্ণহীন অক্ষগুলি উপেক্ষা করার জন্য আপনি আপনার ম্যাটপ্ল্লিটিব ব্যাকেন্ডগুলি সেট আপ করে থাকেন তবে ওয়েেন-ওয়ে লিয়াওয়ের উত্তরটি ভাল; অন্যথায় লুকানো অক্ষগুলি রফতানি করা গ্রাফিকগুলিতে প্রদর্শিত হবে।

আমার উত্তর 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)

এটি সেরা উত্তর ইমো। এটি কার্যকর করা সহজ এবং লেবেলপ্যাড বিকল্পের কারণে লেবেলগুলি ওভারল্যাপ হয় না।
আর্থার ডেন্ট

8

এখানে এমন একটি সমাধান রয়েছে যেখানে আপনি কোনও একটি প্লটের ইলাবেল সেট করেন এবং এর অবস্থানটি সামঞ্জস্য করেন যাতে এটি উল্লম্বভাবে কেন্দ্রীভূত হয়। এইভাবে আপনি কেওয়াইসি দ্বারা উল্লিখিত সমস্যাগুলি এড়াতে পারেন।

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

এখানে চিত্র বর্ণনা লিখুন


7

plt.setp() কাজটি করবে:

# plot something
fig, axs = plt.subplots(3,3, figsize=(15, 8), sharex=True, sharey=True)
for i, ax in enumerate(axs.flat):
    ax.scatter(*np.random.normal(size=(2,200)))
    ax.set_title(f'Title {i}')

# set labels
plt.setp(axs[-1, :], xlabel='x axis label')
plt.setp(axs[:, 0], ylabel='y axis label')

এখানে চিত্র বর্ণনা লিখুন


3
# list loss and acc are your data
fig = plt.figure()
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)

ax1.plot(iteration1, loss)
ax2.plot(iteration2, acc)

ax1.set_title('Training Loss')
ax2.set_title('Training Accuracy')

ax1.set_xlabel('Iteration')
ax1.set_ylabel('Loss')

ax2.set_xlabel('Iteration')
ax2.set_ylabel('Accuracy')

1

অন্যান্য উত্তরের পদ্ধতিগুলি yticks বড় হলে সঠিকভাবে কাজ করবে না। ইয়েলবেল হয় টিক্স দিয়ে ওভারল্যাপ করবে, বামদিকে ক্লিপ হবে বা চিত্রের বাইরে সম্পূর্ণ অদৃশ্য হবে।

আমি হ্যাগেনের উত্তরটি পরিবর্তন করেছি তাই এটি xlabel এবং ইলাবেল উভয়ের জন্যই 1 টিরও বেশি সাবপ্লটগুলির কলামের সাথে কাজ করে এবং এটি চিত্রটিতে ইলাবেলকে দৃশ্যমান রাখার চক্রান্ত স্থানান্তরিত করে।

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

বিকল্পভাবে, আপনি বর্ণহীন অক্ষের সাথে ভাল থাকলে, আমি জুলিয়ান চেনের সমাধানটি পরিবর্তন করেছি যাতে ইয়াবেল টিক লেবেলগুলির সাথে ওভার্যাপল্যাপ না করে।

মূলত, আমাদের বর্ণহীন রঙের ইলিমস সেট করতে হবে তাই এটি সাবপ্লটগুলির বৃহত্তম ইলিমের সাথে মেলে যাতে বর্ণহীন টিক লেবেলগুলি ইলেবেলের সঠিক অবস্থান নির্ধারণ করে।

আবার, ক্লিপিং প্রতিরোধের জন্য আমাদের প্লটটি সঙ্কুচিত করতে হবে। এখানে আমি সঙ্কুচিত হওয়ার জন্য পরিমাণটি কঠোরভাবে কোড করেছি, তবে আপনি এমন কোনও নম্বর খুঁজে পেতে খেলতে পারেন যা আপনার পক্ষে কাজ করে বা উপরের পদ্ধতিতে এটি গণনা করতে পারে।

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()
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.