Salve o plot no arquivo de imagem em vez de exibi-lo usando o Matplotlib

1150

Estou escrevendo um script rápido e sujo para gerar gráficos rapidamente. Estou usando o código abaixo (da documentação do Matplotlib ) como ponto 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

Não quero exibir o gráfico em uma GUI; em vez disso, quero salvar o gráfico em um arquivo (por exemplo, foo.png), para que, por exemplo, ele possa ser usado em scripts em lote. Como faço isso?

Homunculus Reticulli
fonte
85
Parece que eu encontrei a resposta: its pylab.savefig ('foo.png') #
Homunculus Reticulli
2
Talvez o link deva estar vinculado a algum lugar do matplotlib.org?
A.Wan
40
Além disso, se não estiver usando o pylab, o objeto figura também possui um savefigmétodo. Então você pode ligar fig = plt.figure()então fig.savefig(...).
A.Wan
27
Muitas das respostas abaixo da página mencionam o plt.close(fig)que é especialmente importante em grandes loops. Caso contrário, os números permanecem abertas e em espera na memória e todas as figuras abertas serão apresentados a execuçãoplt.show()
timctran
nb: matplotlib.pyplot é o preferido: stackoverflow.com/questions/11469336/…
ErichBSchulz

Respostas:

1441

Enquanto a pergunta foi respondida, gostaria de adicionar algumas dicas úteis ao usar matplotlib.pyplot.savefig . O formato do arquivo pode ser especificado pela extensão:

from matplotlib import pyplot as plt

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

Fornecerá uma saída rasterizada ou vetorizada, respectivamente, ambas que podem ser úteis. Além disso, você verá que pylabdeixa um espaço em branco generoso, geralmente indesejável, ao redor da imagem. Remova-o com:

savefig('foo.png', bbox_inches='tight')
Hooked
fonte
9
É possível alterar as dimensões da imagem resultante?
Llamageddon 28/10/2013
43
@ Asmageddon Para plt.savefigalterar o ppp, consulte o link na resposta. As dimensões podem ser controlados durante a criação da figura, ver figsizeem matplotlib.org/api/figure_api.html#matplotlib.figure.Figure
enganchado
5
@MoTSCHIGGE você pode chamar, o plt.ioff()que deve desativar a interatividade nos matplotlib.pyplotcomandos.
rubenvb
5
@STMohammed foo.png é o caminho. Você pode, por exemplo, colocá-lo em um diretório como este savefig("mydir/foo.png").
Hooked
3
bbox_inches = 'tight' funciona como um encanto. Você fez o meu dia
Catbuilts
205

Como outros já disseram, plt.savefig()ou fig1.savefig()é realmente o caminho para salvar uma imagem.

No entanto, descobri que, em certos casos, a figura é sempre mostrada . (por exemplo, com o Spyder tendo plt.ion(): modo interativo = Ativado.) Eu contorno isso forçando o fechamento da janela de figura no meu loop gigante com plt.close(figure_object)(consulte a documentação ), para não ter um milhão de figuras abertas durante o loop:

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 window

Você deve poder reabrir a figura posteriormente, se necessário fig.show()(não me testou).

Demis
fonte
9
Você também pode definir plt.ioff() # turn of interactive plotting mode, mas isso pode desativar o comportamento que você deseja usar se o seu código sair com um erro.
Demis
2
Você verá o mesmo problema nos notebooks Jupyter. plt.close(fig)
Resolvi
163

A solução é:

pylab.savefig('foo.png')
Lukasz Czerwinski
fonte
89

Acabei de encontrar este link na documentação do MatPlotLib que aborda exatamente esse problema: http://matplotlib.org/faq/howto_faq.html#generate-images-without-having-a-window-appear

Eles dizem que a maneira mais fácil de impedir que a figura apareça é usar um back-end não interativo (por exemplo, Agg), via matplotib.use(<backend>), por exemplo:

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

Eu ainda prefiro usar pessoalmente plt.close( fig ), desde então, você tem a opção de ocultar determinadas figuras (durante um loop), mas ainda exibe figuras para o processamento de dados pós-loop. É provavelmente mais lento do que escolher um back-end não interativo - seria interessante se alguém testasse isso.

UPDATE : para o Spyder, você normalmente não pode definir o back-end dessa maneira (porque o Spyder geralmente carrega o matplotlib mais cedo, impedindo o uso matplotlib.use()).

Em vez disso, use plt.switch_backend('Agg')ou desative " ativar suporte " nas preferências do Spyder e execute o matplotlib.use('Agg')comando você mesmo.

Destas duas dicas: uma , duas

Demis
fonte
1
Isso funciona muito bem para situações em que você não tem uma exibição definida. O uso de outro back-end com .plot()gerará um erro se os.environ['DISPLAY']não estiver definido corretamente.
economia
1
obrigado. isso funciona e é muito útil para servidores de produção em que não há conexão com a internet e precisa do administrador do sistema para instalar quaisquer pacotes.
Leon
Eu gosto do tutorial que o site matplotlib possui para a descrição / definição de "backends": matplotlib.org/tutorials/introductory/…
Tanner Strunk
47

Se você não gosta do conceito da figura "atual", faça:

import matplotlib.image as mpimg

img = mpimg.imread("src.png")
mpimg.imsave("out.png", img)
wonder.mice
fonte
2
Isso não copia apenas src.pngpara out.png?
Gerrit 26/05
Esse é apenas um exemplo, que mostra se você tem um objeto de imagem ( img), então você pode salvá-lo em arquivo com o .imsave()método
wonder.mice
4
@ wonder.mice ajudaria a mostrar como criar uma imagem sem usar a figura atual.
scry
@ wonder.mice Obrigado por este exemplo, é o primeiro que me mostrou como salvar um objeto de imagem em .png.
Arthur Dent
@ Cry Você nem sempre precisa criar uma imagem, às vezes tenta um código e quer uma saída visual, é útil nessas ocasiões.
Schütze
29

As outras respostas estão corretas. No entanto, às vezes acho que quero abrir o objeto de figura mais tarde. Por exemplo, convém alterar os tamanhos dos rótulos, adicionar uma grade ou fazer outro processamento. Em um mundo perfeito, eu simplesmente executaria novamente o código que gerava o enredo e adaptaria as configurações. Infelizmente, o mundo não é perfeito. Portanto, além de salvar em PDF ou PNG, adiciono:

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

Assim, eu posso carregar o objeto da figura e manipular as configurações como quiser.

Também escrevo a pilha com o código-fonte e o locals()dicionário para cada função / método na pilha, para que depois eu possa dizer exatamente o que gerou a figura.

Nota: tenha cuidado, pois às vezes esse método gera arquivos enormes.

gerrit
fonte
não seria mais fácil fazer o desenvolvimento em um notebook jupiter, com os números embutidos? Dessa forma, você pode acompanhar exatamente o histórico e até executá-lo novamente.
Ciprian Tomoiagă
3
@CiprianTomoiaga Eu nunca gero plotagens de produção a partir de um shell interativo em Python (Jupyter ou outro). Eu traço tudo a partir de scripts.
Gerrit
28
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()
Victor Juliet
fonte
28

Depois de usar o plot () e outras funções para criar o conteúdo desejado, você pode usar uma cláusula como essa para selecionar entre plotar na tela ou arquivar:

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()
Mark P.
fonte
Alguns dizem que fig = plt.figure(figuresize=4, 5)poderia serfig = plt.figure(figsize=(4, 5)) #figure sizes in inches
usuário
24

Eu usei o seguinte:

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

Achei muito importante usar o plt.show depois de salvar a figura, caso contrário não funcionará. figura exportada em png

Cristian Muñoz
fonte
2
desculpe, o que é f nisso? arquivo de imagem plotada? f= plt.savefig('data.png')
Morse
14

Você pode fazer:

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

e lembre-se de deixar savefig terminar antes de fechar o gráfico da GUI. Desta forma, você pode ver a imagem de antemão.

Como alternativa, você pode vê-lo com plt.show() Em seguida, feche a GUI e execute o script novamente, mas desta vez substitua plt.show()por plt.savefig().

Como alternativa, você pode usar

fig, ax = plt.figure(nrows=1, ncols=1)
plt.plot(...)
plt.show()
fig.savefig('out.pdf')
Quebra-nozes
fonte
2
obteve um argumento de palavra-chave inesperado 'hold'
amitdatta 6/1217
13

Se, como eu, você usa o Spyder IDE, precisa desativar o modo interativo com:

plt.ioff()

(este comando é iniciado automaticamente com a inicialização científica)

Se você deseja habilitá-lo novamente, use:

plt.ion()

Covich
fonte
12

A solução :

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

Se você deseja exibir a imagem e salvar a imagem, use:

%matplotlib inline

depois de import matplotlib

Durgesh satam
fonte
9

De acordo com a pergunta Matplotlib (pyplot), savefig gera uma imagem em branco .

Uma coisa deve notar: se você usar plt.showe deve depois plt.savefig, ou você dará uma imagem em branco.

Um exemplo detalhado:

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

insira a descrição da imagem aqui

Jayhello
fonte
6
import matplotlib.pyplot as plt
plt.savefig("image.png")

No Jupyter Notebook, você deve remover plt.show()e adicionar plt.savefig(), juntamente com o restante do código plt, em uma célula. A imagem ainda aparecerá no seu notebook.

Punnerud
fonte
1
"remove plt.show ()" .. isso salvou meu dia ...
Guru
4

Dado que hoje (não estava disponível quando esta pergunta foi feita) muitas pessoas usam Jupyter Notebook como console de python, há uma maneira extremamente fácil para salvar as parcelas como .png, basta ligar para o matplotlib's pylabclasse de Jupyter Notebook, traçar a figura' inline 'jupyter células e arraste essa figura / imagem para um diretório local. Não esqueça %matplotlib inlinena primeira linha!

Hamidreza
fonte
1
é uma boa idéia, basta anotar o impacto no tamanho do arquivo se a imagem for deixada incorporada no notebook.
prusswan
3

Além dos itens acima, adicionei __file__o nome para que a imagem e o arquivo Python obtenham os mesmos nomes. Também adicionei alguns argumentos para torná-lo melhor:

# 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'

fonte
2

Ao usar matplotlib.pyplot, você deve primeiro salvar sua plotagem e depois fechá-la usando estas 2 linhas:

fig.savefig('plot.png') # save the plot, place the path you want to save the figure in quotation
plt.close(fig) # close the figure window
Gelo silencioso
fonte
1

Como sugerido anteriormente, você pode usar:

import matplotlib.pyplot as plt
plt.savefig("myfig.png")

Para salvar qualquer imagem IPhython que você está exibindo. Ou em uma nota diferente (olhando de um ângulo diferente), se você trabalhar com o cv aberto ou se tiver importado o cv aberto, poderá optar por:

importação cv2

cv2.imwrite ("myfig.png", imagem)

Mas isso é apenas no caso, se você precisar trabalhar com o Open CV. Caso contrário, plt.savefig () deve ser suficiente.

Aditya Bhattacharya
fonte
0

Você pode salvar sua imagem com qualquer extensão (png, jpg, etc.) E com a resolução desejada. Aqui está uma função para salvar sua figura.

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' é o nome pelo qual você deseja salvar sua figura. Espero que ajude:)

Rudresh Dixit
fonte
0

Você pode fazer assim:

def plotAFig():
  plt.figure()
  plt.plot(x,y,'b-')
  plt.savefig("figurename.png")
  plt.close()
Mark90
fonte