web-dev-qa-db-fra.com

Enregistrer le tracé dans un fichier image au lieu de l'afficher à l'aide de Matplotlib

J'écris un script rapide pour générer des parcelles à la volée. J'utilise le code ci-dessous (de Matplotlib documentation) comme point de départ:

from pylab import figure, axes, pie, title, show

# Make a square figure and axes
figure(1, figsize=(6, 6))
ax = axes([0.1, 0.1, 0.8, 0.8])

labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
fracs = [15, 30, 45, 10]

explode = (0, 0.05, 0, 0)
pie(fracs, explode=explode, labels=labels, autopct='%1.1f%%', shadow=True)
title('Raining Hogs and Dogs', bbox={'facecolor': '0.8', 'pad': 5})

show()  # Actually, don't show, just save to foo.png

Je ne souhaite pas afficher le tracé sur une interface graphique, mais l'enregistrer dans un fichier (par exemple, foo.png), afin que, par exemple, il puisse être utilisé dans des scripts batch. Comment je fais ça?

988

Bien que la question ait été résolue, j'aimerais ajouter quelques conseils utiles lors de l'utilisation de matplotlib.pyplot.savefig . Le format de fichier peut être spécifié par l'extension:

from matplotlib import pyplot as plt

plt.savefig('foo.png')
plt.savefig('foo.pdf')

Donnera une sortie pixellisée ou vectorisée, ce qui pourrait être utile. De plus, vous constaterez que pylab laisse un espace vide généreux, souvent indésirable, autour de l'image. Retirez-le avec:

savefig('foo.png', bbox_inches='tight')
1221
Hooked

Comme d'autres l'ont dit, plt.savefig() ou fig1.savefig() est en effet le moyen de sauvegarder une image.

Cependant, j'ai constaté que dans certains cas (par exemple avec Spyder ayant plt.ion(): mode interactif = On), le chiffre est toujours affiché. Je contourne cela en forçant la fermeture de la fenêtre de la figure dans ma boucle géante. Je n'ai donc pas un million de figures ouvertes pendant la boucle:

import matplotlib.pyplot as plt
fig, ax = plt.subplots( nrows=1, ncols=1 )  # create figure & 1 axis
ax.plot([0,1,2], [10,20,3])
fig.savefig('path/to/save/image/to.png')   # save the figure to file
plt.close(fig)    # close the figure
169
Demis

La solution est:

pylab.savefig('foo.png')
155
Lukasz Czerwinski

Je viens de trouver ce lien dans la documentation MatPlotLib qui aborde exactement ce problème: http://matplotlib.org/faq/howto_faq.html#generate-images-without-haout-have-a-window-appear

Ils disent que le moyen le plus simple d'empêcher l'apparition de la figure est d'utiliser un système non interactif (par exemple, Agg), via matplotib.use(<backend>), par exemple:

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.savefig('myfig')

Personnellement, je préfère toujours utiliser plt.close( fig ), car vous avez alors la possibilité de masquer certains chiffres (pendant une boucle), tout en affichant des chiffres pour le traitement des données après la boucle. Il est probablement plus lent que de choisir un serveur non interactif, ce qui serait intéressant si quelqu'un testait cela.

UPDATE: pour Spyder, vous ne pouvez généralement pas définir le back-end de cette manière (car Spyder charge généralement matplotlib tôt, vous empêchant d'utiliser matplotlib.use()). .

Utilisez plutôt plt.switch_backend('Agg') ou désactivez " enable support " dans les préférences Spyder et exécutez vous-même la commande matplotlib.use('Agg').

De ces deux astuces: one , two

79
Demis

Si vous n'aimez pas le concept du chiffre "actuel", faites:

import matplotlib.image as mpimg

img = mpimg.imread("src.png")
mpimg.imsave("out.png", img)
43
wonder.mice

Les autres réponses sont correctes. Cependant, je trouve parfois que je veux ouvrir la figure objet plus tard. Par exemple, je souhaiterais peut-être modifier la taille des étiquettes, ajouter une grille ou effectuer un autre traitement. Dans un monde parfait, je voudrais simplement réexécuter le code qui génère l'intrigue et adapter les paramètres. Hélas, le monde n'est pas parfait. Par conséquent, en plus d’enregistrer PDF ou PNG, j’ajoute:

with open('some_file.pkl', "wb") as fp:
    pickle.dump(fig, fp, protocol=4)

Comme cela, je peux plus tard charger l'objet figure et manipuler les paramètres comme bon me semble.

J'écris aussi la pile avec le code-source et le dictionnaire locals() pour chaque fonction/méthode de la pile, de manière à pouvoir dire plus tard exactement ce qui a généré le chiffre.

NB: Attention, cette méthode génère parfois d’énormes fichiers.

26
gerrit

Après avoir utilisé plot () et d'autres fonctions pour créer le contenu souhaité, vous pouvez utiliser une clause telle que celle-ci pour choisir entre le traçage à l'écran ou le fichier:

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(4, 5))       # size in inches
# use plot(), etc. to create your plot.

# Pick one of the following lines to uncomment
# save_file = None
# save_file = os.path.join(your_directory, your_file_name)  

if save_file:
    plt.savefig(save_file)
    plt.close(fig)
else:
    plt.show()
26
Mark P.
import datetime
import numpy as np
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt

# Create the PdfPages object to which we will save the pages:
# The with statement makes sure that the PdfPages object is closed properly at
# the end of the block, even if an Exception occurs.
with PdfPages('multipage_pdf.pdf') as pdf:
    plt.figure(figsize=(3, 3))
    plt.plot(range(7), [3, 1, 4, 1, 5, 9, 2], 'r-o')
    plt.title('Page One')
    pdf.savefig()  # saves the current figure into a pdf page
    plt.close()

    plt.rc('text', usetex=True)
    plt.figure(figsize=(8, 6))
    x = np.arange(0, 5, 0.1)
    plt.plot(x, np.sin(x), 'b-')
    plt.title('Page Two')
    pdf.savefig()
    plt.close()

    plt.rc('text', usetex=False)
    fig = plt.figure(figsize=(4, 5))
    plt.plot(x, x*x, 'ko')
    plt.title('Page Three')
    pdf.savefig(fig)  # or you can pass a Figure object to pdf.savefig
    plt.close()

    # We can also set the file's metadata via the PdfPages object:
    d = pdf.infodict()
    d['Title'] = 'Multipage PDF Example'
    d['Author'] = u'Jouni K. Sepp\xe4nen'
    d['Subject'] = 'How to create a multipage pdf file and set its metadata'
    d['Keywords'] = 'PdfPages multipage keywords author title subject'
    d['CreationDate'] = datetime.datetime(2009, 11, 13)
    d['ModDate'] = datetime.datetime.today()
24
Victor Juliet

J'ai utilisé ce qui suit:

import matplotlib.pyplot as plt

p1 = plt.plot(dates, temp, 'r-', label="Temperature (celsius)")  
p2 = plt.plot(dates, psal, 'b-', label="Salinity (psu)")  
plt.legend(loc='upper center', numpoints=1, bbox_to_anchor=(0.5, -0.05),        ncol=2, fancybox=True, shadow=True)

plt.savefig('data.png')  
plt.show()  
f.close()
plt.close()

J'ai trouvé très important d'utiliser plt.show après avoir sauvegardé la figure, sinon cela ne fonctionnera pas . figure exportée en png

21
Cristian Muñoz

Vous pouvez soit faire:

plt.show(hold=False)
plt.savefig('name.pdf')

et rappelez-vous de laisser savefig terminer avant de fermer le graphique. De cette façon, vous pouvez voir l'image à l'avance.

Vous pouvez également le regarder avec plt.show(), puis fermez l'interface graphique et relancez le script, mais cette fois, remplacez plt.show() par plt.savefig().

Alternativement, vous pouvez utiliser

fig, ax = plt.figure(nrows=1, ncols=1)
plt.plot(...)
plt.show()
fig.savefig('out.pdf')
12
Nutcracker

La solution :

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
matplotlib.style.use('ggplot')
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
ts = ts.cumsum()
plt.figure()
ts.plot()
plt.savefig("foo.png", bbox_inches='tight')

Si vous souhaitez afficher l'image et sauvegarder l'image, utilisez:

%matplotlib inline

après import matplotlib

11
Durgesh satam

Si, comme moi, vous utilisez Spyder IDE, vous devez désactiver le mode interactif avec:

plt.ioff()

(cette commande est automatiquement lancée avec le démarrage scientifique)

Si vous souhaitez l'activer à nouveau, utilisez:

plt.ion()

11
Covich

Selon la question Matplotlib (pyplot) savefig génère une image vide .

Une chose à noter: si vous utilisez plt.show et que vous devriez le faire après plt.savefig, vous obtiendrez une image vierge.

Un exemple détaillé:

import numpy as np
import matplotlib.pyplot as plt


def draw_result(lst_iter, lst_loss, lst_acc, title):
    plt.plot(lst_iter, lst_loss, '-b', label='loss')
    plt.plot(lst_iter, lst_acc, '-r', label='accuracy')

    plt.xlabel("n iteration")
    plt.legend(loc='upper left')
    plt.title(title)
    plt.savefig(title+".png")  # should before plt.show method

    plt.show()


def test_draw():
    lst_iter = range(100)
    lst_loss = [0.01 * i + 0.01 * i ** 2 for i in xrange(100)]
    # lst_loss = np.random.randn(1, 100).reshape((100, ))
    lst_acc = [0.01 * i - 0.01 * i ** 2 for i in xrange(100)]
    # lst_acc = np.random.randn(1, 100).reshape((100, ))
    draw_result(lst_iter, lst_loss, lst_acc, "sgd_method")


if __== '__main__':
    test_draw()

enter image description here

6
Jayhello
#write the code for the plot     
plt.savefig("filename.png")

Le fichier sera sauvegardé dans le même répertoire que le fichier python/Jupyter en cours d’exécution.

5
Swaraj Kumar
import matplotlib.pyplot as plt
plt.savefig("image.png")

Dans Jupyter Notebook, vous devez supprimer plt.show() et ajouter plt.savefig(), ainsi que le reste du code plt dans une cellule. L'image sera toujours affichée dans votre cahier.

4
Punnerud

Étant donné qu'aujourd'hui (n'était pas disponible lorsque cette question a été posée), de nombreuses personnes utilisent Jupyter Notebook en tant que console python, il existe un moyen extrêmement simple d'enregistrer les parcelles sous le nom .png, il suffit d'appeler le matplotlib. pylab class de Jupyter Notebook, tracez la cellule 'inline' jupyter de la figure, puis faites-la glisser dans un répertoire local. N'oubliez pas %matplotlib inline en première ligne!

3
Hamidreza

En plus de ceux ci-dessus, j'ai ajouté __file__ pour le nom afin que l'image et le fichier Python aient les mêmes noms. J'ai également ajouté quelques arguments pour que cela paraisse mieux:

# Saves a PNG file of the current graph to the folder and updates it every time
# (nameOfimage, dpi=(sizeOfimage),Keeps_Labels_From_Disappearing)
plt.savefig(__file__+".png",dpi=(250), bbox_inches='tight')
# Hard coded name: './test.png'

Dernier conseil trouvé ICI .

1
r_e

Vous pouvez enregistrer votre image avec n’importe quelle extension (png, jpg, etc.) et avec la résolution souhaitée. Voici une fonction pour enregistrer votre personnage.

import os

def save_fig(fig_id, tight_layout=True, fig_extension="png", resolution=300):
    path = os.path.join(IMAGES_PATH, fig_id + "." + fig_extension)
    print("Saving figure", fig_id)
    if tight_layout:
        plt.tight_layout()
    plt.savefig(path, format=fig_extension, dpi=resolution)

'fig_id' est le nom sous lequel vous voulez sauvegarder votre personnage. J'espère que ça aide:)

0
Rudresh Dixit