2010-10-28 45 views
116

Tengo dificultades para lidiar con los márgenes de mi trazado en matplotlib. He utilizado el código de abajo para producir mi carta:Reduce los márgenes izquierdo y derecho en el gráfico matplotlib

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

Sin embargo, me sale una cifra de producción con una gran cantidad de espacio en blanco a ambos lados de la trama. Busqué en google y leí la documentación de matplotlib, pero parece que no puedo encontrar cómo reducir esto.

+0

¿El problema es la cantidad de espacio en blanco en el '' extent' del imshow' cifra, o la cantidad de espacio en blanco del borde en el png resultante, alrededor de la figura, generado por 'savefig'? – unutbu

+0

Creo que ambas: parece que hay mucho espacio tanto en la ventana de visualización como en PNG. Sin embargo, el resultado importante es el archivo png producido por 'savefig', así que eso es lo que me gustaría ordenar. – robintw

+0

Luego los recogí en GIMP. :/ – endolith

Respuesta

160

Una forma de hacerlo automáticamente es bbox_inches='tight' kwarg a plt.savefig.

E.g.

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

Otra forma es utilizar 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') 
+4

¿Hay alguna manera de hacer esto el valor predeterminado? – endolith

+1

Si tiene múltiples subtramas y desea guardar cada una de ellas, puede usar esto con 'fig.savefig()' también. ('plt.savefig()' no funcionará en ese caso.) –

+1

Todo lo que hace es recortar la imagen después de que se ha procesado; si intenta imponer una resolución en particular, la imagen saldrá * más pequeña *. – detly

93

Puede ajustar el espacio en torno a figuras matplotlib utilizando el subplots_adjust() Función:

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

Esto funciona tanto para la figura de pantalla y guardada en un archivo, y es la función correcta para llamar incluso si no tiene múltiples trazados en la figura.

Los números son fracciones de las dimensiones de la figura, y deberán ajustarse para permitir las etiquetas de las figuras.

+6

Los valores asignados a los parámetros y no la cantidad para cambiarlos, son dónde establecer el margen. En otras palabras, si desea aumentar el margen de borde derecho en un 10%, debe establecer right = 0.9, no right = 0.1 http://matplotlib.sourceforge.net/api/pyplot_api.html#matplotlib.pyplot.subplots_adjust – drootang

+1

Tiene sentido señalar que, obviamente, puede especificar valores negativos en plt.subplots_adjust(). Hacerlo incluso te permite dibujar fuera del área de la figura y también para lidiar con márgenes molestos. – surchs

+0

Esto también funciona en objetos 'GridSpec' llamando al método' update' (vea http://stackoverflow.com/a/20058199/1030876). –

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

"pad_inches = -1" porque mi savefig solo produce parte de la figura. –

+0

El uso de un parámetro en la función 'savefig' es elegante, sin embargo, el valor negativo para' pad_inches' no es necesariamente necesario en todos los casos. – MichaelHuelsen

+0

configúralo a 0, ayuda a – Joop

3

El problema con matplotlibs subplots_adjust es que los valores que se introducen son relativas a la X e Y figsize de la figura. Este ejemplo es para figuresizing correcta para la impresión de un pdf:

Para eso, volver a calcular la separación relativa a los valores absolutos como esto:

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) 

para una figura de pulgadas 'figure.xsize' en x- dimensiones y 'figura.maño' pulgadas en dimensión y. Entonces, toda la figura tiene un margen izquierdo de 5 mm, un margen inferior de 4 mm, una derecha de 1 mm y una parte superior de 3 mm dentro de las etiquetas. La conversión de (x/25.4) se hace porque necesitaba convertir mm a pulgadas.

Tenga en cuenta que el tamaño del gráfico pura de x será "figure.xsize - margen izquierdo - margen derecho" y el tamaño del gráfico pura de y será "figure.ysize - margen inferior - margen superior" en pulgadas

otros

sniplets (no estoy seguro acerca de estos, sólo quería para proporcionar los otros parámetros)

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

y

pyplot.savefig("outputname.eps", dpi = 100) 
+3

de dónde obtuviste 'xsize' y' ysize' from. Yo uso esas propiedades y obtengo 'AttributeError: 'Figure' objeto no tiene atributo 'xsize'' – cj5

+0

ver aquí: http://stackoverflow.com/a/43502756/4473230 – theCake

37

Todo lo que necesita es

plt.tight_layout() 

antes de su salida.

Además de la tala de los márgenes, esto también herméticamente el espacio entre los grupos de las tramas secundarias:

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

Creo que este es realmente el mejor método.No es necesario guardar la figura como 'bbox = 'tight' y corrige todo tipo de problemas de diseño en cifras estrechas. – dshepherd

+1

esta debería ser la respuesta correcta porque se comporta como es de esperar ya que se aplica a la FIGURA en lugar de a la imagen. –

1

Para mí, las respuestas anteriores no funcionaron con matplotlib.__version__ = 1.4.3 en Win7.Entonces, si solo estamos interesados ​​en la imagen en sí (es decir, si no necesitamos anotaciones, ejes, ticks, título, ylabel, etc.), entonces es mejor simplemente guardar la matriz numpy como imagen en lugar de 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) 

Además, el uso funciones de dibujo OpenCV (cv2.line, cv2.polylines), podemos hacer unos dibujos directamente en la matriz numpy. http://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html

5

Simplemente use "ax = fig.add_axes ([left, bottom, width, height])" si desea un control exacto del diseño de la figura. p.ej.

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

inspirado por Sammys respuesta anterior:

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) 

Dónde figsize es la tupla que utilizó en fig = pyplot.figure(figsize=...)

Cuestiones relacionadas