Migliora la dimensione / la spaziatura della sottotrama con molte sottotrame in matplotlib


313

Molto simile a questa domanda, ma con la differenza che la mia figura può essere grande quanto deve essere.

Ho bisogno di generare un sacco di grafici in pila verticale in matplotlib. Il risultato verrà salvato usando figsave e visualizzato su una pagina Web, quindi non mi interessa quanto sia alta l'immagine finale fintanto che i sottotrame sono spaziati in modo che non si sovrappongano.

Non importa quanto grande consenta che la figura sia, le sottotrame sembrano sempre sovrapporsi.

Il mio codice attualmente sembra

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)

Risposte:


413

Prova a usare plt.tight_layout

A titolo di esempio:

import matplotlib.pyplot as plt

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

plt.show()

Senza layout stretto

inserisci qui la descrizione dell'immagine


Con layout stretto inserisci qui la descrizione dell'immagine


21
Sarebbe un po 'più chiaro se mostri che dovresti eseguirlo dopo il codice della trama, ma proprio prima di show ()
pyj

5
tight_layout()è incostante. Ho cercato di capire cosa è diverso quando non ha alcun effetto (restano ampi margini tra le trame) - il che è spesso
javadba

3
Questo ha funzionato abbastanza bene per me, tranne che ha sovrapposto il titolo della mia figura ( suptitle) al titolo della mia sottotrama. Nel caso in cui qualcuno dovesse riscontrare un problema simile, ecco cosa mi ha aiutato nel mio caso stackoverflow.com/a/45161551/11740420 . Vale a dire, il rectparametro ditight_layout()
Siyana Pavlova,

285

È possibile utilizzare plt.subplots_adjustper modificare la spaziatura tra i grafici secondari (origine)

firma della chiamata:

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

I significati dei parametri (e i valori predefiniti suggeriti) sono:

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

I valori predefiniti effettivi sono controllati dal file rc


3
Ho provato a fare confusione con hspace, ma aumentarlo sembra solo ridurre tutti i grafici senza risolvere il problema di sovrapposizione. Ho provato a giocare anche con gli altri parametri, ma non so cosa ci siano effettivamente sinistra, destra, in basso e in alto.
mcstrother,

52
@mcstrother puoi modificare interattivamente tutti e 6 questi parametri se fai clic sul pulsante 'regolazione' dopo aver mostrato un grafico, quindi copiali nel codice una volta trovato ciò che funziona.
Nick T,

1
Non vedo un pulsante di regolazione. Anche se sono su un quaderno Jupyter. Ho provato% matplotlib inline e% matplotlib notebook.
Matt Kleinsmith,

1
@MattKleinsmith: il pulsante di regolazione presenta il testo al passaggio del mouse "Configura sottotrame" e viene visualizzato in normali utilizzi non su notebook di Matplotlib. È il pulsante a sinistra del pulsante di salvataggio "floppy disk" qui: pythonspot-9329.kxcdn.com/wp-content/uploads/2016/07/… - nota che il pulsante ha un aspetto diverso a seconda del sistema di finestre che stai utilizzando, ma è sempre a sinistra del pulsante Salva.
John Zwinck,

@JohnZwinck, il link nel tuo commento è morto ora.
user4015990

56

Ho scoperto che subplots_adjust (hspace = 0.001) è quello che ha finito per funzionare per me. Quando uso space = None, c'è ancora spazio bianco tra ogni trama. Impostarlo su qualcosa molto vicino allo zero sembra tuttavia costringerli ad allinearsi. Quello che ho caricato qui non è il pezzo di codice più elegante, ma puoi vedere come funziona 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()

inserisci qui la descrizione dell'immagine


31
import matplotlib.pyplot as plt

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

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

o

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

Le dimensioni dell'immagine contano.

"Ho provato a fare confusione con hspace, ma aumentarlo sembra solo ridurre tutti i grafici senza risolvere il problema di sovrapposizione."

Pertanto, per rendere più spazio bianco e mantenere le dimensioni della trama secondaria, l'immagine totale deve essere più grande.


2
Le dimensioni dell'immagine contano, dimensioni più grandi dell'immagine possono risolvere questo problema! set plt.figure(figsize=(10, 7)), la dimensione dell'immagine sarebbe 2000 x 1400pix
Belter


20

Simile a tight_layoutmatplotlib ora (dalla versione 2.2) fornisce constrained_layout. Al contrario tight_layout, che può essere chiamato in qualsiasi momento nel codice per un singolo layout ottimizzato, constrained_layoutè una proprietà, che può essere attiva e ottimizzare il layout prima di ogni passaggio del disegno.

Quindi deve essere attivato prima o durante la creazione della sottotrama, come figure(constrained_layout=True)o subplots(constrained_layout=True).

Esempio:

import matplotlib.pyplot as plt

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

plt.show()

inserisci qui la descrizione dell'immagine

vincined_layout può anche essere impostato tramite rcParams

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

Vedi le novità e la Guida al layout vincolato


1
andando a provare questo: non avevo visto questa opzione - ed tight_layoutè inaffidabile
javadba

questo sembrava promettente ma non mi dava abbastanza spazio (etichette degli assi e titoli ancora sovrapposti) e il rendering richiedeva molto più tempo. tight_layout()ha funzionato meglio
Iraq

2
@craq Corretto, in generale contrained_layoutè più lento, perché come visto in questa risposta, ottimizza il layout prima di ogni passaggio del disegno .
ImportanceOfBeingErnest

per me questa è stata la risposta più utile - tight_layout per me migliora sempre la spaziatura verticale per lasciare spazio al titolo del pannello, ma a costo di tagliare ogni volta l'etichetta dell'asse y. Questo, invece, funziona perfettamente, grazie.
Adrian Tompkins,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.