Frage Gemeinsames Xlabel / Ylabel für Matplotlib-Unterplots


Ich habe folgende Handlung:

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

und jetzt möchte ich diesem Diagramm gemeinsame X-Achsen-Etiketten und Y-Achsen-Etiketten geben. Mit "gemeinsam" meine ich, dass es unter dem gesamten Raster von Unterplots ein großes X-Achsen-Etikett und auf der rechten Seite ein großes Y-Achsen-Etikett geben sollte. Ich kann nichts darüber in der Dokumentation für finden plt.subplotsund meine googlings legen nahe, dass ich ein großes machen muss plt.subplot(111) um damit anzufangen - aber wie stelle ich dann meine 5 * 2 Subplots in diese mit ein plt.subplots?


76
2018-04-22 15:25


Ursprung


Antworten:


Das sieht so aus, als ob Sie wirklich wollen. Es gilt der gleiche Ansatz von diese Antwort zu Ihrem speziellen Fall:

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



Ohne sharex=True, sharey=True du erhältst:

enter image description here

Damit solltest du es schöner machen:

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

Wenn Sie jedoch zusätzliche Beschriftungen hinzufügen möchten, sollten Sie diese nur den Randdiagrammen hinzufügen:

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

Das Hinzufügen eines Labels für jedes Plot würde es verderben (vielleicht gibt es eine Möglichkeit, wiederholte Labels automatisch zu erkennen, aber mir ist eines nicht bekannt).


27
2018-05-13 18:21



Seit dem Befehl:

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

Du benutzt ein Tupel, das aus der Figur und einer Liste der Achseninstanzen besteht, es genügt bereits, etwas zu tun (beachte, dass ich mich geändert habe) fig,axzu 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')

Wenn Sie einige Details zu einem bestimmten Unterplot ändern möchten, können Sie darauf über zugreifen axes[i] woher i iteriert über Ihre Unterplots.

Es könnte auch sehr hilfreich sein, ein

fig.tight_layout()

am Ende der Datei, vor der plt.show(), um überlappende Etiketten zu vermeiden.


14
2018-04-22 17:49



Ich stieß auf ein ähnliches Problem, als ich ein Raster von Graphen zeichnete. Die Graphen bestanden aus zwei Teilen (oben und unten). Das y-Label sollte über beide Teile zentriert sein.

Ich wollte keine Lösung verwenden, die von der Position in der äußeren Figur abhängt (wie fig.text ()), also manipulierte ich die y-Position der Funktion set_ylabel (). Es ist normalerweise 0,5, die Mitte der Handlung, zu der es hinzugefügt wird. Da der Abstand zwischen den Teilen (hspace) in meinem Code Null war, konnte ich die Mitte der beiden Teile relativ zum oberen Teil berechnen.

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

Bild

Nachteile:

  • Der horizontale Abstand zum Plot basiert auf dem oberen Teil, die unteren Ticks können sich in das Label erstrecken.

  • Die Formel berücksichtigt keinen Abstand zwischen den Teilen.

  • Es wird eine Ausnahme ausgelöst, wenn die Höhe des oberen Teils 0 ist.

Es gibt wahrscheinlich eine allgemeine Lösung, die das Auffüllen zwischen den Zahlen berücksichtigt.


2
2017-07-27 16:35



Ich habe eine robustere Methode entdeckt:

Wenn du das weißt bottom und top Kwargs, die in eine gingen GridSpec Initialisierung, oder Sie kennen sonst die Kantenpositionen Ihrer Achsen Figure Koordinaten, können Sie auch die Position des Labels angeben Figure koordiniert mit etwas Fantasie "verwandeln" Magie. Beispielsweise:

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

... und du solltest das Etikett sehen passt sich immer noch richtig links-rechts an damit sie sich nicht wie bei normalen Tickletiketten überlappen, aber jetzt wird sie sich immer anpassen genau zwischen die gewünschten Subplots.

Außerdem, wenn Sie nicht einmal verwenden set_position, das Ylabel wird standardmäßig angezeigt genau auf halber Höhe. Ich schätze, das ist, weil wenn das Label endlich gezeichnet ist, matplotlib verwendet 0,5 für die y-koordinieren, ohne zu prüfen, ob sich die zugrunde liegende Koordinatentransformation geändert hat.


1
2018-05-17 09:07



Es wird besser aussehen, wenn Sie Platz für die allgemeinen Etiketten reservieren, indem Sie unsichtbare Beschriftungen für das Teilplot in der unteren linken Ecke machen. Es ist auch gut, die Schriftgröße von rcParams zu übergeben. Auf diese Weise ändern die gebräuchlichen Etiketten die Größe mit Ihrer RC-Einrichtung, und die Achsen werden ebenfalls angepasst, um Platz für die gebräuchlichen Etiketten zu lassen.

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