Popraw rozmiar / odstępy podplotów dzięki wielu podplotom w matplotlib

313

Bardzo podobny do tego pytania, ale z tą różnicą, że moja postać może być tak duża, jak powinna.

Muszę wygenerować całą masę pionowo ułożonych wykresów w matplotlib. Wynik zostanie zapisany za pomocą figsave i wyświetlony na stronie internetowej, więc nie obchodzi mnie, jak wysoki jest końcowy obraz, o ile podploty są rozmieszczone w odstępach, aby się nie nakładały.

Bez względu na to, jak duże pozwolę figurze, wykresy cząstkowe zawsze wydają się nakładać.

Mój kod obecnie wygląda

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
źródło

Odpowiedzi:

413

Spróbuj użyć plt.tight_layout

Jako szybki przykład:

import matplotlib.pyplot as plt

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

plt.show()

Bez ciasnego układu

wprowadź opis zdjęcia tutaj


Z ciasnym układem wprowadź opis zdjęcia tutaj

Joe Kington
źródło
21
Byłoby trochę jaśniej, gdybyś pokazał, że powinieneś wykonać to po kodzie fabuły, ale tuż przed show ()
pyj
5
tight_layout()jest strzałem w dziesiątkę. Próbowałem zrozumieć, co jest inne, gdy nie ma to żadnego efektu (pozostają duże marginesy między
fabułami
3
Działa to całkiem dobrze dla mnie, z tym wyjątkiem, że nałożyło mój tytuł figure ( suptitle) na mój tytuł wątku. Jeśli ktoś napotka podobny problem, oto, co pomogło w mojej sprawie stackoverflow.com/a/45161551/11740420 . Mianowicie rectparametrtight_layout()
Siyana Pavlova
284

Możesz użyć, plt.subplots_adjustaby zmienić odstępy między podplotami (źródło)

podpis połączenia:

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

Znaczenie parametrów (i sugerowane wartości domyślne) to:

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

Rzeczywiste wartości domyślne są kontrolowane przez plik rc

CyanRook
źródło
3
Próbowałem zadzierać z hspace, ale zwiększenie go wydaje się jedynie zmniejszać wszystkie wykresy bez rozwiązania problemu nakładania się. Próbowałem również grać z innymi parametrami, ale nie wiem, co tak naprawdę określa lewe, prawe, dolne i górne.
mcstrother
52
@mcstrother możesz interaktywnie zmienić wszystkie 6 z tych parametrów, jeśli klikniesz przycisk „dostosowanie” po wyświetleniu wykresu, a następnie skopiujesz je do kodu, gdy tylko znajdziesz, co działa.
Nick T
1
Nie widzę przycisku regulacji. Chociaż jestem w notesie Jupyter. Próbowałem% matplotlib inline i% matplotlib notebooka.
Matt Kleinsmith,
1
@MattKleinsmith: Przycisk dostosowania ma tekst „Konfiguruj podploty” i pojawia się w regularnych zastosowaniach Matplotlib poza notebookami. Jest to przycisk po lewej stronie przycisku zapisu „dyskietki” tutaj: pythonspot-9329.kxcdn.com/wp-content/uploads/2016/07/… - zwróć uwagę, że przycisk wygląda inaczej w zależności od systemu okien, w którym jesteś za pomocą, ale zawsze znajduje się po lewej stronie przycisku Zapisz.
John Zwinck
@JohnZwinck, link w twoim komentarzu jest już nieaktualny.
użytkownik4015990
56

Przekonałem się, że subplots_adjust (hspace = 0,001) właśnie to dla mnie działa. Kiedy używam spacji = Brak, pomiędzy poszczególnymi polami nadal jest biała przestrzeń. Wydaje się jednak, że ustawienie wartości zbliżonej do zera zmusza ich do wyrównania. To, co tu przesłałem, nie jest najbardziej eleganckim fragmentem kodu, ale możesz zobaczyć, jak działa hspace.

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

wprowadź opis zdjęcia tutaj

Alexa Halford
źródło
31
import matplotlib.pyplot as plt

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

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

lub

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

Rozmiar zdjęcia ma znaczenie.

„Próbowałem zadzierać z hspace, ale zwiększenie go wydaje się jedynie zmniejszać wszystkie wykresy bez rozwiązania problemu nakładania się”.

Zatem, aby uzyskać więcej białej przestrzeni i utrzymać rozmiar podsuwki, całkowity obraz musi być większy.

The Demz
źródło
2
Rozmiar zdjęcia ma znaczenie, większy rozmiar obrazu może rozwiązać ten problem! ustawiony plt.figure(figsize=(10, 7))rozmiar obrazu to 2000 x 1400pix
Belter
20

Podobny do tight_layoutmatplotlib teraz (od wersji 2.2) zapewnia constrained_layout. W przeciwieństwie do tight_layout, który można wywołać w dowolnym momencie kodu dla pojedynczego zoptymalizowanego układu,constrained_layout jest właściwością, która może być aktywna i zoptymalizuje układ przed każdym krokiem rysowania.

Dlatego należy go aktywować przed lub podczas tworzenia podplotu, takiego jak figure(constrained_layout=True)lubsubplots(constrained_layout=True) .

Przykład:

import matplotlib.pyplot as plt

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

plt.show()

wprowadź opis zdjęcia tutaj

constrained_layout można również ustawić za pomocą rcParams

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

Zobacz nowość i przewodnik dotyczący układu ograniczonego

WażnośćOfBeingErnest
źródło
1
zamierzam to wypróbować: nie widziałem tej opcji - i tight_layoutjest zawodny
javadba
brzmiało to obiecująco, ale nie dawało mi wystarczających odstępów (etykiety osi i tytuły nadal się pokrywały), a renderowanie trwało znacznie dłużej. tight_layout()działało lepiej
craq
2
@craq Prawidłowo, ogólnie contrained_layoutjest wolniejszy, ponieważ jak widać w tej odpowiedzi, optymalizuje układ przed każdym krokiem rysowania .
WażnośćOfertyErnest
dla mnie była to najbardziej użyteczna odpowiedź - tight_layout dla mnie zawsze poprawia pionowe odstępy, aby zostawić miejsce na tytuł panelu, ale kosztem odcięcia etykiety osi y za każdym razem. To działa idealnie, dzięki.
Adrian Tompkins