2011-11-01 33 views
74

Estoy tratando de hacer un gráfico cuadrado (usando imshow), es decir, una relación de aspecto de 1: 1, pero no puedo. Ninguno de estos trabajos:¿Cómo puedo establecer la relación de aspecto en matplotlib?

import matplotlib.pyplot as plt 

ax = fig.add_subplot(111,aspect='equal') 
ax = fig.add_subplot(111,aspect=1.0) 
ax.set_aspect('equal') 
plt.axes().set_aspect('equal') 

Parece que las llamadas son simplemente ser ignorado (un problema que a menudo parecen tener con matplotlib).

+5

¿Has probado 'ax.axis ('equal')', por casualidad? Como todos dijeron, lo que hiciste debería funcionar, pero 'ax.axis' podría ser otra ruta para intentar una solución. –

+0

http://matplotlib.org/examples/pylab_examples/equal_aspect_ratio.html –

Respuesta

53

En tercer lugar el encanto. Supongo que esto es un error y Zhenya's answer sugiere que esté arreglado en la última versión. Tengo la versión 0.99.1.1 y he creado la siguiente solución:

import matplotlib.pyplot as plt 
import numpy as np 

def forceAspect(ax,aspect=1): 
    im = ax.get_images() 
    extent = im[0].get_extent() 
    ax.set_aspect(abs((extent[1]-extent[0])/(extent[3]-extent[2]))/aspect) 

data = np.random.rand(10,20) 

fig = plt.figure() 
ax = fig.add_subplot(111) 
ax.imshow(data) 
ax.set_xlabel('xlabel') 
ax.set_aspect(2) 
fig.savefig('equal.png') 
ax.set_aspect('auto') 
fig.savefig('auto.png') 
forceAspect(ax,aspect=1) 
fig.savefig('force.png') 

Ésta es 'force.png': enter image description here

continuación son mis intentos sin éxito, sin embargo, es de esperar informativos.

Segunda respuesta:

Mi 'respuesta original' a continuación es una exageración, ya que hace algo similar a axes.set_aspect(). Creo que quieres usar axes.set_aspect('auto'). No entiendo por qué este es el caso, pero produce una parcela cuadrado por mí, por ejemplo, esta secuencia de comandos:

import matplotlib.pyplot as plt 
import numpy as np 

data = np.random.rand(10,20) 

fig = plt.figure() 
ax = fig.add_subplot(111) 
ax.imshow(data) 
ax.set_aspect('equal') 
fig.savefig('equal.png') 
ax.set_aspect('auto') 
fig.savefig('auto.png') 

produce una trama de imagen con 'igual' relación de aspecto: enter image description here y uno con 'auto' relación de aspecto: enter image description here

El código proporcionado a continuación en la 'respuesta original' proporciona un punto de partida para una relación de aspecto explícitamente controlada, pero parece ignorarse una vez que se llama a imshow.

respuesta original:

Aquí está un ejemplo de una rutina que ajustar los parámetros de subparcelas de manera que se obtiene la relación de aspecto deseada:

import matplotlib.pyplot as plt 

def adjustFigAspect(fig,aspect=1): 
    ''' 
    Adjust the subplot parameters so that the figure has the correct 
    aspect ratio. 
    ''' 
    xsize,ysize = fig.get_size_inches() 
    minsize = min(xsize,ysize) 
    xlim = .4*minsize/xsize 
    ylim = .4*minsize/ysize 
    if aspect < 1: 
     xlim *= aspect 
    else: 
     ylim /= aspect 
    fig.subplots_adjust(left=.5-xlim, 
         right=.5+xlim, 
         bottom=.5-ylim, 
         top=.5+ylim) 

fig = plt.figure() 
adjustFigAspect(fig,aspect=.5) 
ax = fig.add_subplot(111) 
ax.plot(range(10),range(10)) 

fig.savefig('axAspect.png') 

Esto produce una figura de este modo: enter image description here

Me imagino que si tienes múltiples subtramas dentro de la figura, tienes Me gustaría incluir el número de subparcelas yy x como parámetros de palabras clave (valor predeterminado en 1 cada uno) a la rutina provista. Luego, usando esos números y las palabras clave hspace y wspace, puede hacer que todas las subtramas tengan la proporción de aspecto correcta.

+0

Muchas gracias. ¡Finalmente, funciona la función! Gracias, gracias :-) – jtlz2

+0

Para los casos donde 'get_images' es una lista vacía (como pasaría con' ax.plot ([0,1], [0,2]) ', puedes usar' get_xlim' y ' get_ylim' – Joel

+0

Me parece que esto no funcionará si lo hago con la escala de registro. He agregado una respuesta que lo prueba y lo maneja. Siéntase libre de incorporarlo a su respuesta y luego eliminaré la mía. – Joel

2

debe intentar con figaspect. Esto funciona para mi. De los documentos:

Cree una figura con relación de aspecto especificada. Si arg es un número, use esa relación de aspecto. > Si arg es una matriz, figaspect se determinar el ancho y la altura de una figura que encajaría array conservando la relación de aspecto. El ancho y la altura de la figura en pulgadas son devueltos. Asegúrese de crear un eje con la misma anchura y altura, por ejemplo

Ejemplo de uso:

# make a figure twice as tall as it is wide 
    w, h = figaspect(2.) 
    fig = Figure(figsize=(w,h)) 
    ax = fig.add_axes([0.1, 0.1, 0.8, 0.8]) 
    ax.imshow(A, **kwargs) 

    # make a figure with the proper aspect for an array 
    A = rand(5,3) 
    w, h = figaspect(A) 
    fig = Figure(figsize=(w,h)) 
    ax = fig.add_axes([0.1, 0.1, 0.8, 0.8]) 
    ax.imshow(A, **kwargs) 

Editar: No estoy seguro de lo que busca. El código anterior cambia el lienzo (el tamaño de la gráfica). Si desea cambiar el tamaño de la ventana matplotlib, de la figura, a continuación, utilizar:

In [68]: f = figure(figsize=(5,1)) 

esto produzca una ventana de 5x1 (ancho x alto).

+0

Gracias por esto, tiene algún efecto, al cambiar la relación de aspecto del lienzo: Para ser más específico, necesito cambiar la relación de aspecto del figurar a sí mismo, que haciendo lo siguiente no (formato de las aplicaciones ...): fig = plt.figure (figsize = (plt.figaspect (2.0))) – jtlz2

17

¿Cuál es la versión matplotlib que está ejecutando? Recientemente tuve que actualizar a 1.1.0, y con él, add_subplot(111,aspect='equal') funciona para mí.

+0

Es 1.0.1. Tal vez esa sea una respuesta. – jtlz2

+0

Funciona bien para mí en 'matplotlib' version' 2.0.2'. 'Jupyter notebook' version' 5.0.0'. Gracias. – Sathish

1

Esta respuesta se basa en la respuesta de Yann. Establecerá la relación de aspecto para gráficos lineales o log-log. He utilizado información adicional de https://stackoverflow.com/a/16290035/2966723 para probar si los ejes son logarítmicos.

def forceAspect(ax,aspect=1): 
    #aspect is width/height 
    scale_str = ax.get_yaxis().get_scale() 
    xmin,xmax = ax.get_xlim() 
    ymin,ymax = ax.get_ylim() 
    if scale_str=='linear': 
     asp = abs((xmax-xmin)/(ymax-ymin))/aspect 
    elif scale_str=='log': 
     asp = abs((scipy.log(xmax)-scipy.log(xmin))/(scipy.log(ymax)-scipy.log(ymin)))/aspect 
    ax.set_aspect(asp) 

Obviamente se puede utilizar cualquier versión de log desea, he utilizado scipy, pero numpy o math debe estar bien.

Cuestiones relacionadas