J'essaie de faire un tracé carré (en utilisant imshow), c'est-à-dire un rapport de format de 1: 1, mais je ne peux pas. Aucun de ces travaux:
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')
Il semble que les appels soient simplement ignorés (un problème que je semble souvent avoir avec matplotlib).
Troisième fois le charme. Mon hypothèse est qu'il s'agit d'un bogue et réponse de Zhenya suggère qu'il soit corrigé dans la dernière version. J'ai la version 0.99.1.1 et j'ai créé la solution suivante:
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')
C'est 'force.png':
Vous trouverez ci-dessous mes tentatives infructueuses, mais heureusement informatives.
Deuxième réponse:
Ma "réponse originale" ci-dessous est excessive, car elle a un effet similaire à axes.set_aspect()
. Je pense que vous voulez utiliser axes.set_aspect('auto')
. Je ne comprends pas pourquoi c'est le cas, mais cela produit un tracé d'image carrée pour moi, par exemple ce script:
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')
Produit un tracé d’image avec un rapport de format 'égal': et un avec le rapport d'aspect 'auto':
Le code fourni ci-dessous dans la "réponse originale" fournit un point de départ pour un rapport de format explicitement contrôlé, mais il semble être ignoré une fois qu'un imshow est appelé.
Réponse originale:
Voici un exemple de routine qui ajustera les paramètres de la sous-parcelle afin d'obtenir le rapport d'aspect souhaité:
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')
Cela produit une figure comme celle-ci:
Je peux imaginer que si vous avez plusieurs sous-parcelles dans la figure, vous voudriez inclure le nombre de sous-parcelles y et x en tant que paramètres de mot-clé (par défaut, 1 chacun) à la routine fournie. Ensuite, en utilisant ces nombres et les mots-clés hspace
et wspace
, vous pouvez faire en sorte que toutes les sous-parcelles aient le rapport hauteur/largeur correct.
Quelle est la version matplotlib
que vous utilisez? J'ai récemment dû passer à 1.1.0
, et avec lui, add_subplot(111,aspect='equal')
fonctionne pour moi.
vous devriez essayer avec figaspect. Ça marche pour moi. De la docs:
Créez une figure avec un rapport d'aspect spécifié. Si arg est un nombre, utilisez ce format. > Si arg est un tableau, figaspect déterminera la largeur et la hauteur d'une figure qui conviendrait au tableau en préservant les proportions. La largeur de la figure, la hauteur en pouces sont renvoyées. Assurez-vous de créer un axe avec la même hauteur et la même hauteur, par exemple
Exemple d'utilisation:
# 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)
Edit: Je ne suis pas sûr de ce que vous recherchez. Le code ci-dessus modifie le canevas (la taille du tracé). Si vous voulez changer la taille de la fenêtre matplotlib, de la figure, utilisez:
In [68]: f = figure(figsize=(5,1))
cela produit une fenêtre de 5x1 (lxh).
Cette réponse est basée sur la réponse de Yann. Il définira les proportions des tracés linéaires ou log-log. J'ai utilisé des informations supplémentaires provenant de https://stackoverflow.com/a/16290035/296672 pour vérifier si les axes sont à l'échelle du journal.
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)
Évidemment, vous pouvez utiliser n’importe quelle version de log
, j’ai utilisé scipy
, mais numpy
ou math
devrait aller.
Après plusieurs années de succès avec les réponses ci-dessus, j’ai trouvé que cela ne fonctionnait plus - mais j’ai trouvé une solution de travail pour les sous-parcelles sur
https://jdhao.github.io/2017/06/03/change-aspect-ratio-in-mpl
Avec tout le mérite de l'auteur ci-dessus (qui peut peut-être plutôt poster ici), les lignes pertinentes sont:
ratio = 1.0
xleft, xright = ax.get_xlim()
ybottom, ytop = ax.get_ylim()
ax.set_aspect(abs((xright-xleft)/(ybottom-ytop))*ratio)
Le lien contient également une explication claire des différents systèmes de coordonnées utilisés par matplotlib.
Merci pour toutes les bonnes réponses reçues - en particulier @ Yann qui restera le gagnant.