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.


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

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.


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

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

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.


4
plt.savefig("circle.png", bbox_inches='tight',pad_inches=-1)

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)

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=...)


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


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.