Verbessern Sie die Größe / den Abstand von Unterplots mit vielen Unterplots in matplotlib

312

Sehr ähnlich zu dieser Frage, aber mit dem Unterschied, dass meine Figur so groß sein kann, wie sie sein muss.

Ich muss eine ganze Reihe von vertikal gestapelten Plots in matplotlib generieren. Das Ergebnis wird mit figsave gespeichert und auf einer Webseite angezeigt. Es ist mir also egal, wie hoch das endgültige Bild ist, solange die Unterzeichnungen voneinander beabstandet sind, damit sie sich nicht überlappen.

Egal wie groß ich die Figur sein lasse, die Nebenhandlungen scheinen sich immer zu überlappen.

Mein Code sieht derzeit so aus

import matplotlib.pyplot as plt
import my_other_module

titles, x_lists, y_lists = my_other_module.get_data()

fig = plt.figure(figsize=(10,60))
for i, y_list in enumerate(y_lists):
    plt.subplot(len(titles), 1, i)
    plt.xlabel("Some X label")
    plt.ylabel("Some Y label")
    plt.title(titles[i])
    plt.plot(x_lists[i],y_list)
fig.savefig('out.png', dpi=100)
mcstrother
quelle

Antworten:

412

Versuchen Sie es mit plt.tight_layout

Als schnelles Beispiel:

import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=4, ncols=4)
fig.tight_layout() # Or equivalently,  "plt.tight_layout()"

plt.show()

Ohne enges Layout

Geben Sie hier die Bildbeschreibung ein


Mit engem Layout Geben Sie hier die Bildbeschreibung ein

Joe Kington
quelle
21
Es wäre etwas klarer, wenn Sie zeigen, dass Sie dies nach Ihrem
Plotcode
5
tight_layout()ist ein Hit und Miss. Ich habe versucht zu verstehen, was anders ist, wenn es keine Wirkung hat (große Ränder zwischen den Plots bleiben) - was oft der
Fall
3
Dies funktionierte ziemlich gut für mich, außer dass es meinen Figurentitel ( suptitle) mit meinem Nebenhandlungstitel überlagerte . Falls jemand auf ein ähnliches Problem stößt, hat in meinem Fall stackoverflow.com/a/45161551/11740420 Folgendes geholfen . Der rectParameter vontight_layout()
Siyana Pavlova
283

Sie können plt.subplots_adjustden Abstand zwischen den Unterplots (Quelle) ändern.

Anrufsignatur:

subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)

Die Parameterbedeutungen (und die vorgeschlagenen Standardeinstellungen) sind:

left  = 0.125  # the left side of the subplots of the figure
right = 0.9    # the right side of the subplots of the figure
bottom = 0.1   # the bottom of the subplots of the figure
top = 0.9      # the top of the subplots of the figure
wspace = 0.2   # the amount of width reserved for blank space between subplots
hspace = 0.2   # the amount of height reserved for white space between subplots

Die tatsächlichen Standardeinstellungen werden von der RC-Datei gesteuert

CyanRook
quelle
3
Ich habe versucht, mit hspace herumzuspielen, aber durch Erhöhen werden nur alle Diagramme kleiner, ohne das Überlappungsproblem zu lösen. Ich habe versucht, auch mit den anderen Parametern zu spielen, aber ich weiß nicht, was links, rechts, unten und oben dort tatsächlich spezifizieren.
Mcstrother
52
@mcstrother Sie können alle 6 dieser Parameter interaktiv ändern, wenn Sie nach dem Anzeigen eines Diagramms auf die Schaltfläche "Anpassung" klicken und sie dann in den Code kopieren, sobald Sie herausgefunden haben, was funktioniert.
Nick T
1
Ich sehe keinen Einstellknopf. Obwohl ich in einem Jupyter-Notizbuch bin. Ich habe% matplotlib inline und% matplotlib notebook ausprobiert.
Matt Kleinsmith
1
@MattKleinsmith: Die Anpassungsschaltfläche enthält den Hover-Text "Configure subplots" und wird in regulären Nicht-Notebook-Anwendungen von Matplotlib angezeigt. Dies ist die Schaltfläche links neben der Schaltfläche zum Speichern der Diskette hier: pythonspot-9329.kxcdn.com/wp-content/uploads/2016/07/… - Beachten Sie, dass die Schaltfläche je nach Fenstersystem unterschiedlich aussieht mit, aber es ist immer links von der Schaltfläche Speichern.
John Zwinck
@ JohnZwinck, der Link in deinem Kommentar ist jetzt tot.
user4015990
56

Ich fand, dass subplots_adjust (hspace = 0.001) für mich funktioniert hat. Wenn ich Leerzeichen = Keine verwende, befindet sich zwischen den einzelnen Plots immer noch ein Leerzeichen. Das Setzen auf etwas sehr nahe an Null scheint sie jedoch zu zwingen, sich auszurichten. Was ich hier hochgeladen habe, ist nicht der eleganteste Code, aber Sie können sehen, wie der hspace funktioniert.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as tic

fig = plt.figure()

x = np.arange(100)
y = 3.*np.sin(x*2.*np.pi/100.)

for i in range(5):
    temp = 510 + i
    ax = plt.subplot(temp)
    plt.plot(x,y)
    plt.subplots_adjust(hspace = .001)
    temp = tic.MaxNLocator(3)
    ax.yaxis.set_major_locator(temp)
    ax.set_xticklabels(())
    ax.title.set_visible(False)

plt.show()

Geben Sie hier die Bildbeschreibung ein

Alexa Halford
quelle
31
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(10,60))
plt.subplots_adjust( ... )

Die Methode plt.subplots_adjust :

def subplots_adjust(*args, **kwargs):
    """
    call signature::

      subplots_adjust(left=None, bottom=None, right=None, top=None,
                      wspace=None, hspace=None)

    Tune the subplot layout via the
    :class:`matplotlib.figure.SubplotParams` mechanism.  The parameter
    meanings (and suggested defaults) are::

      left  = 0.125  # the left side of the subplots of the figure
      right = 0.9    # the right side of the subplots of the figure
      bottom = 0.1   # the bottom of the subplots of the figure
      top = 0.9      # the top of the subplots of the figure
      wspace = 0.2   # the amount of width reserved for blank space between subplots
      hspace = 0.2   # the amount of height reserved for white space between subplots

    The actual defaults are controlled by the rc file
    """
    fig = gcf()
    fig.subplots_adjust(*args, **kwargs)
    draw_if_interactive()

oder

fig = plt.figure(figsize=(10,60))
fig.subplots_adjust( ... )

Die Größe des Bildes ist wichtig.

"Ich habe versucht, mit hspace herumzuspielen, aber durch Erhöhen werden nur alle Diagramme kleiner, ohne das Überlappungsproblem zu lösen."

Um mehr Leerraum zu schaffen und die Größe des Untergrundstücks beizubehalten, muss das Gesamtbild größer sein.

Der Demz
quelle
2
Die Größe des Bildes ist wichtig, eine größere Bildgröße kann dieses Problem lösen! eingestellt plt.figure(figsize=(10, 7)), die Größe des Bildes wäre 2000 x 1400pix
Belter
19

Ähnlich wie tight_layoutMatplotlib jetzt (ab Version 2.2) bietet constrained_layout. Im Gegensatz zu tight_layout, die jederzeit im Code für ein einzelnes optimiertes Layout aufgerufen werden können,constrained_layout handelt es sich um eine Eigenschaft, die aktiv sein kann und das Layout vor jedem Zeichenschritt .

Daher muss es vor oder während der Erstellung des Unterplots aktiviert werden, z. B. figure(constrained_layout=True)odersubplots(constrained_layout=True) .

Beispiel:

import matplotlib.pyplot as plt

fig, axes = plt.subplots(4,4, constrained_layout=True)

plt.show()

Geben Sie hier die Bildbeschreibung ein

Constrained_layout kann auch über gesetzt werden rcParams

plt.rcParams['figure.constrained_layout.use'] = True

Weitere Informationen finden Sie im neuen Eintrag und im Handbuch für eingeschränktes Layout

Bedeutung von BeErnest
quelle
1
tight_layout
Ich
Wow, die einzige Option, die tatsächlich für mich funktioniert hat
Sergey
Das klang vielversprechend, gab mir aber nicht genügend Abstand (Achsenbeschriftungen und Titel überlappten sich immer noch) und das Rendern dauerte viel länger. tight_layout()hat besser funktioniert
craq
2
@craq Richtig ist im Allgemeinen contrained_layoutlangsamer, da es, wie in dieser Antwort zu sehen ist, das Layout vor jedem Zeichenschritt optimiert .
ImportanceOfBeingErnest
Für mich war dies die nützlichste Antwort. Tight_layout verbessert für mich immer den vertikalen Abstand, um Platz für den Paneltitel zu lassen, jedoch auf Kosten des Abschneidens der Beschriftung der y-Achse jedes Mal. Dies funktioniert stattdessen perfekt, danke.
Adrian Tompkins