web-dev-qa-db-fra.com

Enregistrer une figure après avoir appelé pyplot.show () donne un fichier vide

L'exemple de code suivant génère un tracé simple, puis l'enregistre dans 'fig1.pdf', puis l'affiche et l'enregistre à nouveau dans 'fig2.pdf'. La première image a l'apparence souhaitée, mais la seconde est vierge (contient un carré blanc). Qu'est-ce qui se passe réellement ici? La ligne plt.show() semble déranger quelque chose, mais je ne peux pas comprendre quoi/comment!

import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-1, 1, 100)
y = x**2
plt.plot(x,y)
plt.savefig('fig1.pdf')
plt.show()
plt.savefig('fig2.pdf')
41
andreasdr

Si vous souhaitez enregistrer la figure après l'avoir affichée, vous devez conserver l'instance de la figure. La raison pour laquelle plt.savefig ne fonctionne pas après avoir appelé show est que le chiffre actuel a été réinitialisé.

pyplot garde une trace des figures, axes, etc. qui sont "actuels" (c'est-à-dire qui n'ont pas encore été affichés avec show) en coulisse. gcf et gca obtiennent respectivement la figure actuelle et les instances d'axes courants. plt.savefig (et essentiellement toute autre méthode pyplot) ne fait que plt.gcf().savefig(...). En d'autres termes, obtenez l'instance de figure actuelle et appelez sa méthode savefig. De même, plt.plot fait fondamentalement plt.gca().plot(...).

Après avoir appelé show, la liste des figures et des axes "actuels" est vide.

En général, il vaut mieux utiliser directement les occurrences figure et axes pour tracer/enregistrer/afficher/etc, plutôt que d'utiliser plt.plot, etc., pour obtenir implicitement la figure/les axes actuels et tracer dessus. Il n'y a rien de mal à utiliser pyplot pour tout (surtout de manière interactive), mais il est plus facile de se tirer une balle dans le pied. 

Utilisez pyplot pour plt.show() et pour générer une figure et un ou plusieurs objets axes, mais utilisez ensuite directement les méthodes figure ou axes. (par exemple, ax.plot(x, y) au lieu de plt.plot(x, y), etc.) Le principal avantage de ceci est qu’il est explicite. Vous savez sur quels objets vous traquez et n'avez pas à vous raisonner sur ce que fait la machine à états pyplot (bien que ce ne soit pas difficile de comprendre l'interface machine à états, non plus).

À titre d’exemple de la méthode "recommandée", procédez comme suit:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-1, 1, 100)
y = x**2

fig, ax = plt.subplots()
ax.plot(x, y)
fig.savefig('fig1.pdf')
plt.show()
fig.savefig('fig2.pdf')

Si vous préférez utiliser l'interface pyplot pour tout, saisissez simplement l'instance de figure avant d'appeler show. Par exemple:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-1, 1, 100)
y = x**2

plt.plot(x, y)
fig = plt.gcf()
fig.savefig('fig1.pdf')
plt.show()
fig.savefig('fig2.pdf')
51
Joe Kington

pyplot.show bloque et détruit l'intrigue lors de la fermeture. Vous pouvez utiliser

plt.show(block=False)

après quoi la sauvegarde sur fig2.pdf fonctionnera ou vous pourrez la tracer à nouveau avant de sauvegarder

plt.plot(x,y)
plt.savefig('fig2.pdf')
3
miles82

Je devais exécuter plt.cla() et plt.clf() avant de tracer la seconde. Effacer les axes actuels et effacer le tracé actuel, respectivement.

1
Nick Desaulniers

Si vous voulez juste voir le chiffre avant de sauvegarder, vous pouvez appeler 

plt.ion()

avant de tracer, qui démarre le mode interactif , et affiche toutes les figures telles qu'elles sont dessinées . Cela évite généralement d'appeler plt.show(). Vous n'avez plus besoin de fermer les chiffres pour continuer.

Pour désactiver à nouveau le mode interactif, appelez plt.ioff().

0
serv-inc