Guardar la gráfica en un archivo de imagen en lugar de mostrarla usando Matplotlib


Estoy escribiendo un script rápido y sucio para generar gráficas sobre la marcha. Estoy usando el siguiente código (de la documentación de Matplotlib ) como punto de partida:

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

No quiero mostrar la gráfica en una interfaz gráfica de usuario, en su lugar, quiero guardar la gráfica en un archivo (digamos foo.png), por lo que, por ejemplo, se puede utilizar en secuencias de comandos por lotes. ¿Cómo hago eso?

Author: Aurgho Bhattacharjee, 2012-03-08

14 answers

Mientras que la pregunta ha sido respondida, me gustaría añadir algunos consejos útiles al usar savefig. El formato de archivo se puede especificar por la extensión:

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

Dará una salida rasterizada o vectorizada respectivamente, ambas que podrían ser útiles. Además, encontrará que pylab deja un espacio en blanco generoso, a menudo indeseable, alrededor de la imagen. Eliminar con:

savefig('foo.png', bbox_inches='tight')
 950
Author: Hooked,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-05 14:08:22

La solución es:

pylab.savefig('foo.png')
 136
Author: Lukasz Czerwinski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-19 07:37:52

Como otros han dicho, plt.savefig() o fig1.savefig() es de hecho la manera de salvar una imagen.

Sin embargo, he encontrado que en ciertos casos (por ejemplo. con Spyder teniendo plt.ion(): interactive mode = On) la figura siempre se muestra. Trabajo alrededor de esto forzando el cierre de la ventana de figuras en mi bucle gigante, por lo que no tengo un millón de figuras abiertas durante el bucle:

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
 121
Author: Demis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-20 06:12:51

Acabo de encontrar este enlace en la documentación de MatPlotLib que aborda exactamente este problema: http://matplotlib.org/faq/howto_faq.html#generate-images-without-having-a-window-appear

Dicen que la forma más fácil de evitar que la figura aparezca es usar un backend no interactivo (por ejemplo. Agg), via matplotib.use(<backend>), eg:

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

Todavía personalmente prefiero usar plt.close( fig ), ya que entonces tiene la opción de ocultar ciertas figuras (durante un bucle), pero aún así mostrar figuras para post-bucle procesamiento de datos. Sin embargo, es probablemente más lento que elegir un backend no interactivo, sería interesante si alguien lo probara.

 64
Author: Demis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-04 00:35:56

Si no te gusta el concepto de la figura "actual", haz:

import matplotlib.image as mpimg

img = mpimg.imread("src.png")
mpimg.imsave("out.png", img)
 35
Author: wonder.mice,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-19 07:38:20

Las otras respuestas son correctas. Sin embargo, a veces encuentro que quiero abrir el objeto figure más tarde. Por ejemplo, es posible que desee cambiar los tamaños de las etiquetas, agregar una cuadrícula o hacer otro procesamiento. En un mundo perfecto, simplemente volvería a ejecutar el código que genera la trama y adaptaría la configuración. Por desgracia, el mundo no es perfecto. Por lo tanto, además de guardar en PDF o PNG, añado:

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

Así, más tarde puedo cargar el objeto figure y manipular la configuración como favor.

También escribo la pila con el código fuente y el diccionario locals() para cada función/método en la pila, para que luego pueda decir exactamente qué generó la figura.

NB: Tenga cuidado, ya que a veces este método genera archivos enormes.

 25
Author: gerrit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-22 14:14:35
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()
 22
Author: Victor Juliet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-30 08:38:37

Después de usar plot() y otras funciones para crear el contenido que desee, podría usar una cláusula como esta para seleccionar entre graficar en la pantalla o en el archivo:

import matplotlib.pyplot as plt

fig = plt.figure(figuresize=4, 5)
# 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()
 18
Author: Mark P.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-11 22:12:15

Usé lo siguiente:

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

Me pareció muy importante usar plt.mostrar después de guardar la figura, de lo contrario no funcionará. figura exportada en png

 16
Author: Cristian Muñoz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-05 13:58:11

Si, como yo, usas Spyder IDE, tienes que desactivar el modo interactivo con :

plt.ioff()

(este comando se inicia automáticamente con el inicio científico)

Si desea habilitarlo de nuevo, use:

plt.ion()

 11
Author: Covich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-29 14:50:47

La Solución:

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 desea mostrar la imagen, así como guardar la imagen, use:

%matplotlib inline

Después import matplotlib

 10
Author: Durgesh satam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-27 08:59:31

Puedes hacer:

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

Y recuerde dejar que savefig termine antes de cerrar la gráfica GUI. De esta manera se puede ver la imagen de antemano.

Alternativamente, puedes mirarlo con plt.show() Luego cierre la GUI y ejecute el script de nuevo, pero esta vez reemplace plt.show() con plt.savefig().

Alternativamente, puede usar

fig, ax = plt.figure(nrows=1, ncols=1)
plt.plot(...)
plt.show()
fig.savefig('out.pdf')
 10
Author: Nutcracker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-23 23:20:03
#write the code for the plot     
plt.savefig("filename.png")

El archivo se guardará en el mismo directorio que el archivo python/Jupyter que se ejecuta

 3
Author: Swaraj Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-19 06:14:39

De acuerdo con la pregunta Matplotlib (pyplot) savefig produce una imagen en blanco.

Una cosa debe tener en cuenta: si utiliza plt.show y debe después de plt.savefig, o le dará una imagen en blanco.

Un ejemplo detallado:

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 __name__ == '__main__':
    test_draw()

introduzca la descripción de la imagen aquí

 3
Author: Jayhello,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-20 09:38:00