Pertanyaan Xlabel / ylabel umum untuk subplots matplotlib


Saya memiliki plot berikut:

fig,ax = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)

dan sekarang saya ingin memberikan plot ini label x-axis umum dan label y-axis. Dengan "umum", saya berarti bahwa harus ada satu label x-axis besar di bawah seluruh petak subplot, dan satu label y-axis besar ke kanan. Saya tidak dapat menemukan apa pun tentang ini di dokumentasi untuk plt.subplots, dan googling saya menyarankan bahwa saya harus membuat besar plt.subplot(111) untuk mulai dengan - tapi bagaimana saya kemudian menempatkan subplots 5 * 2 saya ke dalam menggunakan itu plt.subplots?


76
2018-04-22 15:25


asal


Jawaban:


Ini terlihat seperti apa yang sebenarnya Anda inginkan. Ini menerapkan pendekatan yang sama jawaban ini untuk kasus spesifik Anda:

import matplotlib.pyplot as plt

fig, ax = plt.subplots(nrows=3, ncols=3, sharex=True, sharey=True, figsize=(6, 6))

fig.text(0.5, 0.04, 'common X', ha='center')
fig.text(0.04, 0.5, 'common Y', va='center', rotation='vertical')

Multiple plots with common axes label


122
2017-11-12 16:56



Tanpa sharex=True, sharey=True Anda mendapatkan:

enter image description here

Dengan itu Anda harus membuatnya lebih baik:

fig, axes2d = plt.subplots(nrows=3, ncols=3,
                           sharex=True, sharey=True,
                           figsize=(6,6))

for i, row in enumerate(axes2d):
    for j, cell in enumerate(row):
        cell.imshow(np.random.rand(32,32))

plt.tight_layout()

enter image description here

Tetapi jika Anda ingin menambahkan label tambahan, Anda harus menambahkannya hanya ke petak tepi:

fig, axes2d = plt.subplots(nrows=3, ncols=3,
                           sharex=True, sharey=True,
                           figsize=(6,6))

for i, row in enumerate(axes2d):
    for j, cell in enumerate(row):
        cell.imshow(np.random.rand(32,32))
        if i == len(axes2d) - 1:
            cell.set_xlabel("noise column: {0:d}".format(j + 1))
        if j == 0:
            cell.set_ylabel("noise row: {0:d}".format(i + 1))

plt.tight_layout()

enter image description here

Menambahkan label untuk setiap plot akan merusaknya (mungkin ada cara untuk secara otomatis mendeteksi label yang berulang, tetapi saya tidak menyadarinya).


27
2018-05-13 18:21



Karena perintahnya:

fig,ax = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)

Anda menggunakan mengembalikan tuple yang terdiri dari gambar dan daftar contoh sumbu, itu sudah cukup untuk melakukan sesuatu seperti (pikiran bahwa saya telah berubah fig,axuntuk fig,axes):

fig,axes = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)

for ax in axes:
    ax.set_xlabel('Common x-label')
    ax.set_ylabel('Common y-label')

Jika Anda kebetulan ingin mengubah beberapa detail pada subplot tertentu, Anda dapat mengaksesnya melalui axes[i] dimana i iterasi atas subplots Anda.

Mungkin juga sangat membantu untuk menyertakan a

fig.tight_layout()

pada akhir file, sebelum plt.show(), untuk menghindari label yang tumpang tindih.


14
2018-04-22 17:49



Saya mengalami masalah yang sama ketika merencanakan grid grafik. Grafik terdiri dari dua bagian (atas dan bawah). Label-y seharusnya dipusatkan di kedua bagian.

Saya tidak ingin menggunakan solusi yang bergantung pada mengetahui posisi pada gambar luar (seperti fig.text ()), jadi saya memanipulasi posisi-y dari fungsi set_ylabel (). Biasanya 0,5, bagian tengah plot ditambahkan. Sebagai padding antara bagian-bagian (hspace) dalam kode saya adalah nol, saya bisa menghitung bagian tengah dari dua bagian relatif ke bagian atas.

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

# Create outer and inner grid
outerGrid = gridspec.GridSpec(2, 3, width_ratios=[1,1,1], height_ratios=[1,1])
somePlot = gridspec.GridSpecFromSubplotSpec(2, 1,
               subplot_spec=outerGrid[3], height_ratios=[1,3], hspace = 0)

# Add two partial plots
partA = plt.subplot(somePlot[0])
partB = plt.subplot(somePlot[1])

# No x-ticks for the upper plot
plt.setp(partA.get_xticklabels(), visible=False)

# The center is (height(top)-height(bottom))/(2*height(top))
# Simplified to 0.5 - height(bottom)/(2*height(top))
mid = 0.5-somePlot.get_height_ratios()[1]/(2.*somePlot.get_height_ratios()[0])
# Place the y-label
partA.set_ylabel('shared label', y = mid)

plt.show()

gambar

Kelemahan:

  • Jarak horizontal ke plot didasarkan pada bagian atas, bagian bawah kutu mungkin meluas ke label.

  • Rumus tidak mengambil ruang antara bagian-bagian ke dalam akun.

  • Melempar pengecualian ketika ketinggian bagian atas adalah 0.

Mungkin ada solusi umum yang memperhitungkan padding di antara angka-angka.


2
2017-07-27 16:35



Saya menemukan metode yang lebih kuat:

Jika Anda tahu bottom dan top kwargs yang masuk ke dalam GridSpec inisialisasi, atau Anda tahu posisi ujung sumbu Anda Figure koordinat, Anda juga dapat menentukan posisi ylabel di Figure berkoordinasi dengan sihir "transform" yang mewah. Sebagai contoh:

import matplotlib.transforms as mtransforms
bottom, top = .1, .9
f, a = plt.subplots(nrows=2, ncols=1, bottom=bottom, top=top)
avepos = (bottom+top)/2
a[0].yaxis.label.set_transform(mtransforms.blended_transform_factory(
       mtransforms.IdentityTransform(), f.transFigure # specify x, y transform
       )) # changed from default blend (IdentityTransform(), a[0].transAxes)
a[0].yaxis.label.set_position((0, avepos))
a[0].set_ylabel('Hello, world!')

... dan Anda harus melihat label itu masih menyesuaikan kanan-kiri dengan tepat agar tidak overlapping dengan ticklabel, seperti biasa - tetapi sekarang akan menyesuaikan untuk selalu tepatnya antara subplot yang diinginkan.

Selanjutnya, jika Anda bahkan tidak menggunakannya set_position, ylabel akan muncul secara default tepat di tengah-tengah angka. Saya menduga ini karena ketika label akhirnya ditarik, matplotlib menggunakan 0,5 untuk y-kordinasi tanpa memeriksa apakah transformasi koordinat yang mendasarinya telah berubah.


1
2018-05-17 09:07



Akan terlihat lebih baik jika Anda menyediakan tempat untuk label umum dengan membuat label tak terlihat untuk subplot di sudut kiri bawah. Juga bagus untuk meneruskan fontsize dari rcParams. Dengan cara ini, label umum akan berubah ukuran dengan pengaturan rc Anda, dan sumbu juga akan disesuaikan untuk meninggalkan ruang untuk label umum.

fig_size = [8, 6]
fig, ax = plt.subplots(5, 2, sharex=True, sharey=True, figsize=fig_size)
# Reserve space for axis labels
ax[-1, 0].set_xlabel('.', color=(0, 0, 0, 0))
ax[-1, 0].set_ylabel('.', color=(0, 0, 0, 0))
# Make common axis labels
fig.text(0.5, 0.04, 'common X', va='center', ha='center', fontsize=rcParams['axes.labelsize'])
fig.text(0.04, 0.5, 'common Y', va='center', ha='center', rotation='vertical', fontsize=rcParams['axes.labelsize'])

enter image description here enter image description here


0
2018-05-30 17:57