Comment sharex utiliser subplot2grid

Je suis un utilisateur de Matlab récemment converti en Python. La plupart des compétences en Python que je gère sur mon propre, mais avec le complot j'ai frappé le mur et besoin d'aide.

c'est Ce que je suis en train de faire...

j'ai besoin de faire une figure qui se compose de 3 sous-intrigues avec les propriétés suivantes:

  • la disposition des sous-lots est 311, 312, 313
  • la hauteur de 312 et 313 est environ la moitié du 311
  • toutes les sous-parcelles partagent le même X axe
  • l'espace entre les sous-lots est 0 (ils se touchent à l'axe des X)

par la façon dont je sais faire tout cela, mais pas en un seul chiffre. C'est le problème que je me pose maintenant.

Par exemple, c'est mon idéal intrigue secondaire mise en page:

import numpy as np
import matplotlib.pyplot as plt

t = np.arange(0.0, 2.0, 0.01)

s1 = np.sin(2*np.pi*t)
s2 = np.exp(-t)
s3 = s1*s2

fig = plt.figure()
ax1 = plt.subplot2grid((4,3), (0,0), colspan=3, rowspan=2)
ax2 = plt.subplot2grid((4,3), (2,0), colspan=3)
ax3 = plt.subplot2grid((4,3), (3,0), colspan=3)

ax1.plot(t,s1)
ax2.plot(t[:150],s2[:150])
ax3.plot(t[30:],s3[30:])

plt.tight_layout()

plt.show()

remarquez comment l'axe x des différents sous-lots est mal aligné. Je ne sais pas comment faire pour aligner l'axe des x dans cette figure, mais si je fais quelque chose comme ceci:

import numpy as np
import matplotlib.pyplot as plt

t = np.arange(0.0, 2.0, 0.01)

s1 = np.sin(2*np.pi*t)
s2 = np.exp(-t)
s3 = s1*s2

fig2, (ax1, ax2, ax3) = plt.subplots(nrows=3, ncols=1, sharex=True)

ax1.plot(t,s1)
ax2.plot(t[:150],s2[:150])
ax3.plot(t[30:],s3[30:])

plt.tight_layout()

plt.show()

maintenant le x l'axe est aligné entre les sous-intrigues, mais tous les sous-intrigues sont de la même taille (ce qui n'est pas ce que je veux)

de plus, j'aimerais que les sous-lots touchent à l'axe x comme ceci:

import numpy as np
import matplotlib.pyplot as plt

t = np.arange(0.0, 2.0, 0.01)

s1 = np.sin(2*np.pi*t)
s2 = np.exp(-t)
s3 = s1*s2

fig1 = plt.figure()
plt.subplots_adjust(hspace=0)

ax1 = plt.subplot(311)
ax2 = plt.subplot(312, sharex=ax1)
ax3 = plt.subplot(313, sharex=ax1)

ax1.plot(t,s1)
ax2.plot(t[:150],s2[:150])
ax3.plot(t[30:],s3[30:])

xticklabels = ax1.get_xticklabels()+ax2.get_xticklabels()
plt.setp(xticklabels, visible=False)

plt.show()

alors pour reformuler ma question:

je voudrais utiliser

plt.subplot2grid(..., colspan=3, rowspan=2)
plt.subplots(..., sharex=True)
plt.subplots_adjust(hspace=0)

et

plt.tight_layout()

dans la même figure. Comment faire?

20
demandé sur Boris L. 2014-02-09 20:15:26

2 réponses

spécifiez juste sharex=ax1 lors de la création de vos deuxième et troisième sous-lots.

import numpy as np
import matplotlib.pyplot as plt

t = np.arange(0.0, 2.0, 0.01)

s1 = np.sin(2*np.pi*t)
s2 = np.exp(-t)
s3 = s1*s2

fig = plt.figure()
ax1 = plt.subplot2grid((4,3), (0,0), colspan=3, rowspan=2)
ax2 = plt.subplot2grid((4,3), (2,0), colspan=3, sharex=ax1)
ax3 = plt.subplot2grid((4,3), (3,0), colspan=3, sharex=ax1)

ax1.plot(t,s1)
ax2.plot(t[:150],s2[:150])
ax3.plot(t[30:],s3[30:])

fig.subplots_adjust(hspace=0)   
for ax in [ax1, ax2]:
    plt.setp(ax.get_xticklabels(), visible=False)
    # The y-ticks will overlap with "hspace=0", so we'll hide the bottom tick
    ax.set_yticks(ax.get_yticks()[1:])  

plt.show()

enter image description here

Si vous avez encore ce qu'il faut utiliser fig.tight_layout(), vous aurez besoin de l'appeler avantfig.subplots_adjust(hspace=0). La raison pour cela est que tight_layout fonctionne en calculant automatiquement les paramètres pour subplots_adjust puis en l'appelant, de sorte que si subplots_adjust est manuellement appelé en premier, tout dans le premier appel à lui sera dépassé par tight_layout.

E. G.

fig.tight_layout()
fig.subplots_adjust(hspace=0)
27
répondu Joe Kington 2014-02-09 16:30:33

une solution possible est de créer manuellement l'axe en utilisant le add_axis méthode comme le montre ici:

import numpy as np
import matplotlib.pyplot as plt

t = np.arange(0.0, 2.0, 0.01)

s1 = np.sin(2*np.pi*t)
s2 = np.exp(-t)
s3 = s1*s2

left, width = 0.1, 0.8
rect1 = [left, 0.5, width, 0.4]
rect2 = [left, 0.3, width, 0.15]
rect3 = [left, 0.1, width, 0.15]

fig = plt.figure()
ax1 = fig.add_axes(rect1)  #left, bottom, width, height
ax2 = fig.add_axes(rect2, sharex=ax1)
ax3  = fig.add_axes(rect3, sharex=ax1)

ax1.plot(t,s1)
ax2.plot(t[:150],s2[:150])
ax3.plot(t[30:],s3[30:])

# hide labels
for label1,label2 in zip(ax1.get_xticklabels(),ax2.get_xticklabels()):
    label1.set_visible(False)
    label2.set_visible(False)

plt.show()

mais vous ne pouvez pas utiliser tight_layout comme vous le définir explicitement la taille de chaque axe.

1
répondu Jakob 2014-02-09 16:46:39