Améliorez la taille et l'espacement des sous-parcelles avec de nombreuses sous-parcelles dans matplotlib

313

Très similaire à cette question, mais avec la différence que ma silhouette peut être aussi grande qu'elle doit l'être.

J'ai besoin de générer tout un tas de parcelles empilées verticalement dans matplotlib. Le résultat sera enregistré à l'aide de figsave et affiché sur une page Web, donc je me fiche de la hauteur de l'image finale tant que les sous-tracés sont espacés afin qu'ils ne se chevauchent pas.

Peu importe la taille que j'autorise, les sous-intrigues semblent toujours se chevaucher.

Mon code ressemble actuellement à

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
la source

Réponses:

413

Essayez d'utiliser plt.tight_layout

Comme exemple rapide:

import matplotlib.pyplot as plt

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

plt.show()

Sans mise en page serrée

entrez la description de l'image ici


Avec une disposition serrée entrez la description de l'image ici

Joe Kington
la source
21
Ce serait un peu plus clair si vous montrez que vous devez l'exécuter après votre code de tracé, mais juste avant show ()
pyj
5
tight_layout()est hasardeux. J'ai essayé de comprendre ce qui est différent quand cela n'a aucun effet (de grandes marges inter-parcelles restent) - ce qui est souvent
javadba
3
Cela a plutôt bien fonctionné pour moi, sauf qu'il a superposé le titre de ma figure ( suptitle) avec le titre de mon sous-tracé. Si quelqu'un rencontre un problème similaire, voici ce qui m'a aidé dans mon cas stackoverflow.com/a/45161551/11740420 . À savoir, le rectparamètre detight_layout()
Siyana Pavlova
285

Vous pouvez utiliser plt.subplots_adjustpour modifier l'espacement entre les sous-parcelles (source)

signature d'appel:

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

Les significations des paramètres (et les valeurs par défaut suggérées) sont:

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

Les valeurs par défaut réelles sont contrôlées par le fichier rc

CyanRook
la source
3
J'ai essayé de jouer avec hspace, mais l'augmenter semble seulement rendre tous les graphiques plus petits sans résoudre le problème de chevauchement. J'ai également essayé de jouer avec les autres paramètres, mais je ne sais pas ce que gauche, droite, bas et haut spécifient réellement.
mcstrother
52
@mcstrother, vous pouvez modifier de manière interactive les 6 de ces paramètres si vous cliquez sur le bouton «Réglage» après avoir affiché un tracé, puis copiez-les dans le code une fois que vous avez trouvé ce qui fonctionne.
Nick T
1
Je ne vois pas de bouton de réglage. Bien que je sois dans un cahier Jupyter. J'ai essayé% matplotlib inline et% matplotlib notebook.
Matt Kleinsmith
1
@MattKleinsmith: Le bouton de réglage a le texte de survol "Configurer les sous-tracés" et apparaît dans les utilisations normales de Matplotlib sans bloc-notes. Il s'agit du bouton situé à gauche du bouton de sauvegarde de la «disquette» ici: pythonspot-9329.kxcdn.com/wp-content/uploads/2016/07/… - notez que le bouton est différent en fonction du système de fenêtres que vous utilisez en utilisant, mais il est toujours à gauche du bouton Enregistrer.
John Zwinck
@JohnZwinck, le lien dans votre commentaire est mort maintenant.
user4015990
56

J'ai trouvé que subplots_adjust (hspace = 0,001) est ce qui a fini par fonctionner pour moi. Lorsque j'utilise space = None, il y a toujours un espace blanc entre chaque intrigue. Le mettre à quelque chose de très proche de zéro semble cependant les forcer à s'aligner. Ce que j'ai téléchargé ici n'est pas le morceau de code le plus élégant, mais vous pouvez voir comment fonctionne 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()

entrez la description de l'image ici

Alexa Halford
la source
31
import matplotlib.pyplot as plt

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

La méthode 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()

ou

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

La taille de l'image compte.

"J'ai essayé de jouer avec hspace, mais augmenter cela ne fait que rendre tous les graphiques plus petits sans résoudre le problème de chevauchement."

Ainsi, pour créer plus d'espace blanc et conserver la taille de la sous-parcelle, l'image totale doit être plus grande.

Le Demz
la source
2
La taille de l'image compte, une taille d'image plus grande peut résoudre ce problème! ensemble plt.figure(figsize=(10, 7)), la taille de l'image serait 2000 x 1400pix
Belter
20

Similaire à tight_layoutmatplotlib maintenant (à partir de la version 2.2) fournit constrained_layout. Contrairement à tight_layout, qui peut être appelé à tout moment dans le code pour une mise en page optimisée unique,constrained_layout est une propriété, qui peut être active et optimisera la mise en page avant chaque étape de dessin.

Par conséquent, il doit être activé avant ou pendant la création de la sous-parcelle, comme figure(constrained_layout=True)ousubplots(constrained_layout=True) .

Exemple:

import matplotlib.pyplot as plt

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

plt.show()

entrez la description de l'image ici

constrained_layout peut également être défini via rcParams

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

Voir la nouvelle entrée et le guide de mise en page contraint

ImportanceDeBestErnest
la source
1
va essayer ceci: n'avait pas vu cette option - et tight_layoutn'est pas fiable
javadba
cela semblait prometteur mais ne me donnait pas assez d'espacement (les étiquettes des axes et les titres se chevauchaient toujours) et le rendu prenait beaucoup plus de temps. tight_layout()a mieux fonctionné
craq
2
@craq Correct, en général contrained_layoutest plus lent, car comme vu dans cette réponse, il optimise la mise en page avant chaque étape du dessin .
ImportanceOfBeingErnest
pour moi, c'était la réponse la plus utile - tight_layout pour moi améliore toujours l'espacement vertical pour laisser de la place au titre du panneau, mais au prix de couper l'étiquette de l'axe y à chaque fois. Cela fonctionne plutôt parfaitement, merci.
Adrian Tompkins