Speichern Sie den Plot in einer Bilddatei, anstatt ihn mit Matplotlib anzuzeigen

1150

Ich schreibe ein schnelles und schmutziges Skript, um Handlungen im laufenden Betrieb zu erstellen. Ich verwende den folgenden Code (aus der Matplotlib- Dokumentation) als Ausgangspunkt:

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

Ich möchte den Plot nicht auf einer GUI anzeigen, sondern den Plot in einer Datei (z. B. foo.png) speichern, damit er beispielsweise in Batch-Skripten verwendet werden kann. Wie mache ich das?

Homunculus Reticulli
quelle
85
Sieht so aus, als hätte ich die Antwort gefunden: seine pylab.savefig ('foo.png')
Homunculus Reticulli
2
Link sollte vielleicht irgendwo auf matplotlib.org verlinken?
A.Wan
40
Auch wenn kein Pylab verwendet wird, verfügt das Figurenobjekt über eine savefigMethode. So können Sie rufen fig = plt.figure()dann fig.savefig(...).
A.Wan
27
Viele der Antworten weiter unten auf der Seite erwähnen, plt.close(fig)was besonders bei großen Schleifen wichtig ist. Andernfalls bleiben die Figuren offen und warten im Speicher und alle offenen Figuren werden bei der Ausführung plt.show()
angezeigt
nb: matplotlib.pyplot wird bevorzugt: stackoverflow.com/questions/11469336/…
ErichBSchulz

Antworten:

1438

Während die Frage beantwortet wurde, möchte ich einige nützliche Tipps zur Verwendung von matplotlib.pyplot.savefig hinzufügen . Das Dateiformat kann durch die Erweiterung angegeben werden:

from matplotlib import pyplot as plt

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

Gibt eine gerasterte bzw. vektorisierte Ausgabe, die beide nützlich sein könnten. Darüber hinaus werden Sie feststellen, dass pylabein großzügiges, oft unerwünschtes Leerzeichen um das Bild herum verbleibt. Entfernen Sie es mit:

savefig('foo.png', bbox_inches='tight')
Süchtig
quelle
9
Ist es möglich, die Abmessungen des resultierenden Bildes zu ändern?
Llamageddon
43
@Asmageddon In plt.savefigSie können die dpi ändern, siehe den Link in der Antwort. Die Abmessungen können beim Erstellen der Figur gesteuert werden, siehe figsizein matplotlib.org/api/figure_api.html#matplotlib.figure.Figure
Hooked
5
@MoTSCHIGGE können Sie aufrufen, plt.ioff()wodurch die Interaktivität in matplotlib.pyplotBefehlen deaktiviert werden soll.
Rubenvb
5
@ STMohammed foo.png ist der Pfad. Sie können es beispielsweise in ein solches Verzeichnis einfügen savefig("mydir/foo.png").
Hooked
3
bbox_inches = 'eng' wirkt wie ein Zauber. Du hast meinen Tag gemacht
Catbuilts
205

Wie andere gesagt haben, plt.savefig()oder fig1.savefig()ist in der Tat der Weg, um ein Bild zu speichern.

Ich habe jedoch festgestellt, dass in bestimmten Fällen die Abbildung immer angezeigt wird . (z. B. mit Spyder mit plt.ion(): Interaktiver Modus = Ein.) Um dieses Problem zu umgehen, erzwinge ich das Schließen des Figurenfensters in meiner Riesenschleife mit plt.close(figure_object)(siehe Dokumentation ), sodass ich während der Schleife keine Million offener Figuren habe:

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

Sie sollten in der Lage sein, die Figur später bei Bedarf wieder zu öffnen fig.show()(habe mich nicht getestet).

Demis
quelle
9
Sie können auch festlegen plt.ioff() # turn of interactive plotting mode, aber dies kann das Verhalten deaktivieren, das Sie verwenden möchten, wenn Ihr Code mit einem Fehler beendet wird.
Demis
2
Sie werden das gleiche Problem in Jupyter-Notizbüchern sehen. plt.close(fig)löste es
intsco
163

Die Lösung ist:

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

Ich habe gerade diesen Link in der MatPlotLib-Dokumentation gefunden, der genau dieses Problem behebt: http://matplotlib.org/faq/howto_faq.html#generate-images-without-having-a-window-appear

Sie sagen, dass der einfachste Weg, um das Auftauchen der Figur zu verhindern, die Verwendung eines nicht interaktiven Backends (z. B. Agg) ist, z. matplotib.use(<backend>)B.:

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

Ich persönlich bevorzuge immer noch die Verwendung plt.close( fig ), da Sie seitdem die Möglichkeit haben, bestimmte Zahlen (während einer Schleife) auszublenden, aber immer noch Zahlen für die Datenverarbeitung nach der Schleife anzuzeigen. Es ist wahrscheinlich langsamer als die Auswahl eines nicht interaktiven Backends - wäre interessant, wenn jemand das testen würde.

UPDATE : Für Spyder können Sie das Backend normalerweise nicht auf diese Weise einstellen (da Spyder Matplotlib normalerweise frühzeitig lädt und Sie daran hindert, es zu verwenden matplotlib.use()).

Verwenden plt.switch_backend('Agg')oder deaktivieren Sie stattdessen " Support aktivieren " in den Spyder-Einstellungen und führen Sie den matplotlib.use('Agg')Befehl selbst aus.

Aus diesen beiden Hinweisen: eins , zwei

Demis
quelle
1
Dies funktioniert sehr gut in Situationen, in denen Sie keine festgelegte Anzeige haben. Wenn Sie ein anderes Backend mit verwenden, .plot()wird ein Fehler ausgegeben, wenn os.environ['DISPLAY']es nicht richtig eingestellt ist.
Wirtschaft
1
Vielen Dank. Dies funktioniert und ist sehr hilfreich für Produktionsserver, auf denen keine Internetverbindung besteht und für die Installation von Paketen ein Systemadministrator erforderlich ist.
Leon
Ich mag das Tutorial, das die matplotlib-Site für die Beschreibung / Definition von "Backends" hat: matplotlib.org/tutorials/introductory/…
Tanner Strunk
47

Wenn Ihnen das Konzept der "aktuellen" Figur nicht gefällt, gehen Sie wie folgt vor:

import matplotlib.image as mpimg

img = mpimg.imread("src.png")
mpimg.imsave("out.png", img)
Wonder.mice
quelle
2
Kopiert das nicht einfach src.pngnach out.png?
Gerrit
Dies ist nur ein Beispiel, das zeigt, dass Sie ein Bildobjekt ( img) in einer Datei mit der .imsave()Methode speichern können, wenn Sie es haben .
Wunder. Mäuse
4
@ Wonder.mice würde helfen, zu zeigen, wie man ein Bild erstellt, ohne die aktuelle Abbildung zu verwenden.
Scry
@ Wonder.mice Danke für dieses Beispiel, es ist das erste, das mir gezeigt hat, wie man ein Bildobjekt in .png speichert.
Arthur Dent
@scry Sie müssen nicht immer ein Bild erstellen, manchmal probieren Sie Code aus und möchten eine visuelle Ausgabe. Dies ist in solchen Fällen praktisch.
Schütze
29

Die anderen Antworten sind richtig. Manchmal stelle ich jedoch fest, dass ich das Figurenobjekt später öffnen möchte . Beispielsweise möchte ich möglicherweise die Etikettengrößen ändern, ein Raster hinzufügen oder eine andere Verarbeitung durchführen. In einer perfekten Welt würde ich einfach den Code, der den Plot generiert, erneut ausführen und die Einstellungen anpassen. Leider ist die Welt nicht perfekt. Daher füge ich zusätzlich zum Speichern in PDF oder PNG Folgendes hinzu:

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

So kann ich später das Figurenobjekt laden und die Einstellungen nach Belieben bearbeiten.

Ich schreibe auch den Stapel mit dem Quellcode und dem locals()Wörterbuch für jede Funktion / Methode im Stapel aus, damit ich später genau sagen kann, was die Figur erzeugt hat.

NB: Seien Sie vorsichtig, da diese Methode manchmal große Dateien generiert.

gerrit
quelle
Wäre es nicht einfacher, die Entwicklung in einem Jupyter-Notizbuch mit den Zahlen inline durchzuführen? Auf diese Weise können Sie den Verlauf genau verfolgen und sogar erneut ausführen.
Ciprian Tomoiagă
3
@CiprianTomoiaga Ich generiere niemals Produktionsdiagramme aus einer interaktiven Python-Shell (Jupyter oder anders). Ich zeichne alles aus Skripten.
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
quelle
28

Nachdem Sie mit plot () und anderen Funktionen den gewünschten Inhalt erstellt haben, können Sie mit einer solchen Klausel zwischen dem Plotten auf dem Bildschirm oder der Datei wählen:

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.
quelle
Einige sagen, fig = plt.figure(figuresize=4, 5)könnte seinfig = plt.figure(figsize=(4, 5)) #figure sizes in inches
Benutzer
24

Ich habe folgendes verwendet:

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

Ich fand es sehr wichtig, plt.show nach dem Speichern der Figur zu verwenden, sonst funktioniert es nicht. Abbildung in PNG exportiert

Cristian Muñoz
quelle
2
Entschuldigung, was ist daran? geplottete Bilddatei? f= plt.savefig('data.png')
Morse
14

Sie können entweder:

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

und denken Sie daran, savefig beenden zu lassen, bevor Sie das GUI-Diagramm schließen. Auf diese Weise können Sie das Bild vorher sehen.

Alternativ kann man es auch dreht mit plt.show() Schließen Sie dann die GUI und das Skript erneut aus , diesmal aber ersetzen plt.show()mit plt.savefig().

Alternativ können Sie verwenden

fig, ax = plt.figure(nrows=1, ncols=1)
plt.plot(...)
plt.show()
fig.savefig('out.pdf')
Nussknacker
quelle
2
bekam ein unerwartetes Schlüsselwortargument 'hold'
amitdatta
13

Wenn Sie wie ich Spyder IDE verwenden, müssen Sie den interaktiven Modus deaktivieren mit:

plt.ioff()

(Dieser Befehl wird automatisch mit dem wissenschaftlichen Start gestartet.)

Wenn Sie es erneut aktivieren möchten, verwenden Sie:

plt.ion()

Covich
quelle
12

Die Lösung :

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

Wenn Sie das Bild anzeigen und speichern möchten, verwenden Sie:

%matplotlib inline

nach import matplotlib

Durgesh Satam
quelle
9

Laut Frage gibt Matplotlib (Pyplot) savefig ein leeres Bild aus .

Eine Sache sollte beachtet werden: Wenn Sie verwenden plt.showund es sollte nach plt.savefig, oder Sie werden ein leeres Bild geben.

Ein detailliertes Beispiel:

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

Geben Sie hier die Bildbeschreibung ein

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

In Jupyter Notebook müssen Sie zusammen mit dem Rest des plt-Codes in einer Zelle entfernen plt.show()und hinzufügen plt.savefig(). Das Bild wird weiterhin in Ihrem Notizbuch angezeigt.

Punnerud
quelle
1
"remove plt.show ()" .. das hat mir den Tag gerettet ...
Guru
4

Da heute (nicht verfügbar war , wenn diese Frage gestellt wurde) viele Leute verwenden Jupyter Notebook als Python - Konsole gibt eine äußerst einfache Möglichkeit ist es, die Grundstücke zu speichern , .pngdie, nur nennen matplotlib‚s pylabKlasse von Jupyter Notebook, zeichnet die Figur‘ inline 'jupyter Zellen, und ziehen Sie dann diese Figur / Bild in ein lokales Verzeichnis. Vergessen Sie nicht %matplotlib inlinein der ersten Zeile!

Hamidreza
quelle
1
Das ist eine gute Idee. Beachten Sie nur die Auswirkungen auf die Dateigröße, wenn das Bild im Notizbuch eingebettet bleibt.
Prusswan
3

Zusätzlich zu den oben genannten habe ich __file__den Namen hinzugefügt, damit das Bild und die Python-Datei dieselben Namen erhalten. Ich habe auch einige Argumente hinzugefügt, damit es besser aussieht:

# 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'
Re
quelle
2

Bei der Verwendung matplotlib.pyplotmüssen Sie zuerst Ihr Diagramm speichern und es dann mit den folgenden 2 Zeilen schließen:

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
Silent Ice
quelle
1

Wie bereits vorgeschlagen, können Sie entweder Folgendes verwenden:

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

Zum Speichern des angezeigten IPhython-Bildes. Oder aus einem anderen Blickwinkel (aus einem anderen Blickwinkel), wenn Sie jemals mit Open CV arbeiten oder Open CV importiert haben, können Sie sich für Folgendes entscheiden:

cv2 importieren

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

Dies ist jedoch nur für den Fall, dass Sie mit Open CV arbeiten müssen. Andernfalls sollte plt.savefig () ausreichend sein.

Aditya Bhattacharya
quelle
0

Sie können Ihr Bild mit einer beliebigen Erweiterung (PNG, JPG usw.) Und mit der gewünschten Auflösung speichern. Hier ist eine Funktion zum Speichern Ihrer Figur.

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' ist der Name, unter dem Sie Ihre Figur speichern möchten. Ich hoffe es hilft:)

Rudresh Dixit
quelle
0

Sie können es so machen:

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