Подтвердить что ты не робот

Как использовать sharex при использовании subplot2grid

Я пользователь Matlab, недавно преобразованный в Python. Большинство навыков Python, которыми я управляю самостоятельно, но с заговором я ударил по стене и нуждался в некоторой помощи.

Это то, что я пытаюсь сделать...

Мне нужно сделать фигуру, состоящую из 3 подзаголовков со следующими свойствами:

  • макет подсети 311, 312, 313
  • высота 312 и 313 составляет приблизительно половину 311
  • все подзаголовки имеют общую ось X
  • пространство между подзаголовками равно 0 (они касаются друг друга по оси X)

Кстати, я знаю, как сделать все это, только не в одной фигуре. Это проблема, с которой я сейчас сталкиваюсь.

Например, это мой идеальный макет подзаголовка:

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

Обратите внимание, что ось x разных подзаговоров смещена. Я не знаю, как выровнять ось x на этом рисунке, но если я сделаю что-то вроде этого:

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

Теперь ось x выровнена между подзаголовками, но все подсети имеют одинаковый размер (что не то, что я хочу)

Кроме того, я хотел бы, чтобы подзаголовки касались оси x следующим образом:

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

Чтобы перефразировать мой вопрос:

Я хотел бы использовать

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

и

plt.tight_layout()

вместе на том же рисунке. Как это сделать?

4b9b3361

Ответ 1

Просто укажите sharex=ax1 при создании второго и третьего подзаголовков.

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

Если вы все еще используете fig.tight_layout(), вам нужно позвонить ему до fig.subplots_adjust(hspace=0). Причиной этого является то, что tight_layout работает, автоматически вычисляя параметры для subplots_adjust, а затем вызывая его, поэтому, если subplots_adjust сначала вызывается вручную, все, что было в первом вызове к нему, будет переопределено tight_layout.

например.

fig.tight_layout()
fig.subplots_adjust(hspace=0)

Ответ 2

Возможное решение состоит в том, чтобы вручную создать ось с помощью метода add_axis, как показано здесь:

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

Но таким образом вы не можете использовать tight_layout, поскольку вы явно определяете размер каждой оси.