web-dev-qa-db-fra.com

Créer des sous-parcelles carrées (de hauteur et de largeur égales) dans matplotlib

Quand j'exécute ce code

from pylab import *

figure()
ax1 = subplot(121)
plot([1, 2, 3], [1, 2, 3])
subplot(122, sharex=ax1, sharey=ax1)
plot([1, 2, 3], [1, 2, 3])
draw()
show()

J'obtiens deux sous-intrigues qui sont "écrasées" dans la dimension X. Comment obtenir ces sous-parcelles de telle sorte que la hauteur de l'axe Y soit égale à la largeur de l'axe X, pour les deux sous-parcelles?

J'utilise matplotlib v.0.99.1.2 sur Ubuntu 10.04.

Mise à jour 2010-07-08: Voyons quelques choses qui ne fonctionnent pas.

Après avoir parcouru Google toute la journée, j'ai pensé que cela pourrait être lié à la mise à l'échelle automatique. J'ai donc essayé de jouer avec ça.

from pylab import *

figure()
ax1 = subplot(121, autoscale_on=False)
plot([1, 2, 3], [1, 2, 3])
subplot(122, sharex=ax1, sharey=ax1)
plot([1, 2, 3], [1, 2, 3])
draw()
show()

matplotlib insiste sur la mise à l'échelle automatique.

from pylab import *

figure()
ax1 = subplot(121, autoscale_on=False)
plot([1, 2, 3], [1, 2, 3])
subplot(122, sharex=ax1, sharey=ax1, autoscale_on=False)
plot([1, 2, 3], [1, 2, 3])
draw()
show()

Dans celui-ci, les données disparaissent complètement. WTF, matplotlib? Juste WTF?

D'accord, peut-être que si nous fixons les proportions?

from pylab import *

figure()
ax1 = subplot(121, autoscale_on=False)
plot([1, 2, 3], [1, 2, 3])
axes().set_aspect('equal')
subplot(122, sharex=ax1, sharey=ax1)
plot([1, 2, 3], [1, 2, 3])
draw()
show()

Celui-ci provoque la disparition complète du premier sous-tracé. C'est hilarant! Qui est venu avec celui-là?

Sérieusement, maintenant ... cela devrait-il vraiment être si difficile à accomplir?

23
gotgenes

Votre problème de définition de l'aspect des tracés arrive lorsque vous utilisez sharex et sharey.

Une solution consiste à ne pas utiliser d'axes partagés. Par exemple, vous pouvez faire ceci:

from pylab import *

figure()
subplot(121, aspect='equal')
plot([1, 2, 3], [1, 2, 3])
subplot(122, aspect='equal')
plot([1, 2, 3], [1, 2, 3])
show()

Cependant, une meilleure solution de contournement consiste à modifier le mot-clé "réglable" ... Vous voulez réglable = 'boîte', mais lorsque vous utilisez des axes partagés, il doit être réglable = 'datalim' (et le remettre à 'boîte 'donne une erreur).

Cependant, il existe une troisième option pour que adjustable gère exactement ce cas: adjustable="box-forced".

Par exemple:

from pylab import *

figure()
ax1 = subplot(121, aspect='equal', adjustable='box-forced')
plot([1, 2, 3], [1, 2, 3])
subplot(122, aspect='equal', adjustable='box-forced', sharex=ax1, sharey=ax1)
plot([1, 2, 3], [1, 2, 3])
show()

Ou dans un style plus moderne (note: cette partie de la réponse n'aurait pas fonctionné en 2010):

import matplotlib.pyplot as plt

fig, axes = plt.subplots(ncols=2, sharex=True, sharey=True)
for ax in axes:
    ax.plot([1, 2, 3], [1, 2, 3])
    ax.set(adjustable='box-forced', aspect='equal')

plt.show()

Quoi qu'il en soit, vous obtiendrez quelque chose de similaire à:

enter image description here

21
Joe Kington

Essayez ceci:

from pylab import *

figure()
ax1 = subplot(121, autoscale_on=False, aspect='equal', xlim=[1,3], ylim=[1,3])
plot([1, 2, 3], [1, 2, 3])
##axes().set_aspect('equal')
ax2 = subplot(122, autoscale_on=False, aspect='equal', xlim=[1,3], ylim=[1,3])
plot([1, 2, 3], [1, 2, 3])
draw()
show()

J'ai commenté la ligne axes() car cela créerait un nouveau axes à un emplacement arbitraire, plutôt qu'un subplot préfabriqué avec une position calculée.

L'appel de subplot crée en fait une instance de Axes, ce qui signifie qu'elle peut utiliser les mêmes propriétés que celle d'un Axes.

J'espère que ça aide :)

2
Kit