Reduzieren Sie den linken und rechten Rand im Matplotlib-Plot

178

Ich habe Probleme, mit meinen Handlungsrändern in Matplotlib umzugehen. Ich habe den folgenden Code verwendet, um mein Diagramm zu erstellen:

plt.imshow(g)
c = plt.colorbar()
c.set_label("Number of Slabs")
plt.savefig("OutputToUse.png")

Ich erhalte jedoch eine Ausgabezahl mit viel Leerraum auf beiden Seiten des Diagramms. Ich habe bei Google gesucht und die matplotlib-Dokumentation gelesen, aber ich kann anscheinend nicht herausfinden, wie ich dies reduzieren kann.

robintw
quelle
Ist das Problem der Menge von Leerzeichen in der extentder imshowFigur oder die Menge der Grenze Leerzeichen in der resultierenden png, um die Figur, die durch savefig?
Unutbu
Ich denke beides - es scheint viel Platz sowohl im Sichtfenster als auch im PNG zu geben. Die wichtige Ausgabe ist jedoch die von erzeugte PNG-Datei savefig- das ist es, was ich sortieren möchte.
Robintw
Ich habe sie danach nur in GIMP beschnitten. : /
Endolith

Antworten:

250

Eine Möglichkeit, dies automatisch zu tun, ist das bbox_inches='tight'kwarg to plt.savefig.

Z.B

import matplotlib.pyplot as plt
import numpy as np
data = np.arange(3000).reshape((100,30))
plt.imshow(data)
plt.savefig('test.png', bbox_inches='tight')

Ein anderer Weg ist zu verwenden fig.tight_layout()

import matplotlib.pyplot as plt
import numpy as np

xs = np.linspace(0, 1, 20); ys = np.sin(xs)

fig = plt.figure()
axes = fig.add_subplot(1,1,1)
axes.plot(xs, ys)

# This should be called after all axes have been added
fig.tight_layout()
fig.savefig('test.png')
Joe Kington
quelle
5
Gibt es eine Möglichkeit, dies zum Standard zu machen?
Endolith
1
Wenn Sie mehrere Nebenhandlungen haben und jede von ihnen speichern möchten, können Sie diese auch mit verwenden fig.savefig(). ( plt.savefig()wird in diesem Fall nicht funktionieren.)
Abhranil Das
1
Das Bild wird nur zugeschnitten, nachdem es gerendert wurde. Wenn Sie versuchen, eine bestimmte Auflösung zu erzwingen, wird das Bild kleiner .
Detly
5
@detly - Ja. Das ist genau das, was es tut (obwohl es auch "herausschneiden" und das Bild auch größer machen kann). Schauen Sie sich an, was Sie wollen fig.tight_layout(). Diese Funktion gab es nicht, als diese Antwort ursprünglich geschrieben wurde, sonst würde ich sie stärker erwähnen.
Joe Kington
2
Wenn jemand ein Problem hat, verwenden Siefig = plt.gcf()
KyungHoon Kim
147

Sie können den Abstand um matplotlib-Figuren mit der Funktion subplots_adjust () anpassen:

import matplotlib.pyplot as plt
plt.plot(whatever)
plt.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1)

Dies funktioniert sowohl für die Figur auf dem Bildschirm als auch für das Speichern in einer Datei. Es ist die richtige Funktion, die Sie aufrufen können, auch wenn Sie nicht mehrere Diagramme auf einer Figur haben.

Die Zahlen sind Bruchteile der Figurenabmessungen und müssen angepasst werden, um die Figurenbeschriftungen zu berücksichtigen.

DaveP
quelle
8
Die den Parametern zugewiesenen Werte und nicht, um wie viel sie geändert werden sollen, geben den Rand an. Mit anderen Worten, wenn Sie den rechten Rand um 10% erhöhen
möchten
1
Es ist sinnvoll darauf hinzuweisen, dass Sie in plt.subplots_adjust () natürlich negative Werte angeben können. Auf diese Weise können Sie sogar außerhalb des Figurenbereichs zeichnen und auch mit störenden Rändern umgehen.
Surchs
Dies funktioniert auch bei GridSpecObjekten durch Aufrufen der updateMethode (siehe stackoverflow.com/a/20058199/1030876 ).
Aaron Voelker
57

Alles was Sie brauchen ist

plt.tight_layout()

vor Ihrer Ausgabe.

Dies reduziert nicht nur die Ränder, sondern gruppiert auch den Abstand zwischen den Nebenplots eng:

x = [1,2,3]
y = [1,4,9]
import matplotlib.pyplot as plt
fig = plt.figure()
subplot1 = fig.add_subplot(121)
subplot1.plot(x,y)
subplot2 = fig.add_subplot(122)
subplot2.plot(y,x)
fig.tight_layout()
plt.show()
user2065406
quelle
7
Ich denke, das ist wirklich die beste Methode. Es ist nicht erforderlich, die Figur wie "bbox =" eng "zu speichern und alle anderen Layoutprobleme in beengten Figuren zu beheben.
Dshepherd
2
Dies sollte die richtige Antwort sein, da es sich so verhält, wie Sie es erwarten würden, da es für die ABBILDUNG anstelle des Bildes gilt.
Majid alDosari
Seltsamerweise ändert dies auch die Breite des tatsächlichen Diagramms (dh die Spitzen liegen näher beieinander) im Vergleich zu bbox_inches='tight', wodurch nur der weiße Raum um die Ränder abgeschnitten wird, das Diagramm jedoch in Ruhe gelassen wird. Ich habe die Figur mit erstellt plt.figure(figsize=(10,3)).
Fritz
9

Verwenden ax = fig.add_axes([left, bottom, width, height]) Sie diese Option nur, wenn Sie das Figurenlayout genau steuern möchten. z.B.

left = 0.05
bottom = 0.05
width = 0.9
height = 0.9
ax = fig.add_axes([left, bottom, width, height])
Mason
quelle
6

Falls sich jemand fragt, wie der Rest des weißen Randes nach dem Anwenden entfernt werden kann plt.tight_layout()oder fig.tight_layout(): Mit dem Parameter pad(der 1.08standardmäßig aktiviert ist) können Sie ihn noch enger machen: "Auffüllen zwischen der Figurenkante und den Kanten von Nebenhandlungen als Bruchteil der Schriftgröße. " So zum Beispiel

plt.tight_layout(pad=0.05)

wird es auf einen sehr kleinen Spielraum reduzieren. Das Putten 0funktioniert bei mir nicht, da dadurch auch die Box der Nebenhandlung ein wenig abgeschnitten wird.

Oberwaschlappen
quelle
4
plt.savefig("circle.png", bbox_inches='tight',pad_inches=-1)
Tian Chu
quelle
1
"pad_inches = -1", weil meine savefig nur einen Teil der Figur erzeugt.
Yu Shen
Die Verwendung eines Parameters in der savefigFunktion ist elegant, der negative Wert für pad_incheswird jedoch nicht unbedingt in jedem Fall benötigt.
MichaelHuelsen
setze es auf 0, hilft
Joop
4

Das Problem mit matplotlibs subplots_adjust besteht darin, dass die von Ihnen eingegebenen Werte relativ zur x- und y-Größe der Abbildung sind. Dieses Beispiel dient zur korrekten Abbildung für den Druck eines PDF-Dokuments:

Dafür berechne ich den relativen Abstand zu absoluten Werten wie folgt neu:

pyplot.subplots_adjust(left = (5/25.4)/figure.xsize, bottom = (4/25.4)/figure.ysize, right = 1 - (1/25.4)/figure.xsize, top = 1 - (3/25.4)/figure.ysize)

für eine Zahl von 'figure.xsize' Zoll in x-Dimension und 'figure.ysize' Zoll in y-Dimension. Die ganze Figur hat also einen linken Rand von 5 mm, einen unteren Rand von 4 mm, einen rechten von 1 mm und einen oberen von 3 mm innerhalb der Etiketten. Die Konvertierung von (x / 25.4) erfolgt, weil ich mm in Zoll konvertieren musste.

Beachten Sie, dass die reine Diagrammgröße von x "figure.xsize - linker Rand - rechter Rand" und die reine Diagrammgröße von y "figure.ysize - unterer Rand - oberer Rand" in Zoll ist

Andere Sniplets (nicht sicher, ich wollte nur die anderen Parameter angeben)

pyplot.figure(figsize = figureSize, dpi = None)

und

pyplot.savefig("outputname.eps", dpi = 100)
Sammy
quelle
3
Wo hast du xsizeund ysizeaus. Ich benutze diese Eigenschaften und bekommeAttributeError: 'Figure' object has no attribute 'xsize'
cj5
4

inspiriert von Sammys Antwort oben:

margins = {  #     vvv margin in inches
    "left"   :     1.5 / figsize[0],
    "bottom" :     0.8 / figsize[1],
    "right"  : 1 - 0.3 / figsize[0],
    "top"    : 1 - 1   / figsize[1]
}
fig.subplots_adjust(**margins)

Wo figsize ist das Tupel, in dem Sie verwendet haben fig = pyplot.figure(figsize=...)

michaelosthege
quelle
2

Für mich haben die obigen Antworten unter matplotlib.__version__ = 1.4.3Win7 nicht funktioniert . Wenn wir uns also nur für das Bild selbst interessieren (dh wenn wir keine Anmerkungen, Achsen, Häkchen, Titel, ylabel usw. benötigen), ist es besser, das numpy-Array einfach als Bild zu speichern savefig.

from pylab import *

ax = subplot(111)
ax.imshow(some_image_numpyarray)
imsave('test.tif', some_image_numpyarray)

# or, if the image came from tiff or png etc
RGBbuffer = ax.get_images()[0].get_array()
imsave('test.tif', RGBbuffer)

Mit opencv-Zeichenfunktionen (cv2.line, cv2.polylines) können wir auch einige Zeichnungen direkt auf dem numpy-Array erstellen. http://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html

otterb
quelle
2

In neueren matplotlib-Versionen möchten Sie möglicherweise Constrained Layout ausprobieren .

Michel de Ruiter
quelle