Определите соотношение сторон при использовании twinx

Как установить соотношение сторон для графика, который использует twinx?


Ниже я приведу три примера:

  1. без twinx чтобы подчеркнуть, как я устанавливаю соотношение сторон
  2. только с twinx чтобы проиллюстрировать, как сбрасывается ранее определенное соотношение сторон
  3. моя попытка определить соотношение сторон для обоих yось при использовании twinx (который не работает)

Я использую matplotlib 1.3.0
Следующий скрипт иллюстрирует, как я устанавливаю соотношение сторон простого графика:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,1.6,50) + 50.0

fig = plt.figure()

ax = fig.add_subplot(111)

XLIM = [50.0, 51.6]
YLIM = [0.0, 1.1, 0.0, 11.0] 

ax.plot(x,np.sin(x-50.0),'b')

ax.set_xlim([XLIM[0], XLIM[1]])
ax.set_ylim([YLIM[0], YLIM[1]])

ax.set_xticks(np.arange(XLIM[0], XLIM[1], 0.2))
ax.set_yticks(np.arange(YLIM[0], YLIM[1]+0.1, 0.1)[:-1])

ax.grid(True,which='major',linestyle='solid')

ax.set_aspect((XLIM[1]-XLIM[0])/(YLIM[1]-YLIM[0]))

plt.show()

Рисунок, который это производит, имеет определенное соотношение сторон:

первый сюжет

Однако, если я хочу добавить дополнительный yось с помощью twinx() функция, соотношение сторон сбрасывается:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,1.6,50) + 50.0

fig = plt.figure()

ax = fig.add_subplot(111)
ax2 = ax.twinx()

XLIM = [50.0, 51.6]
YLIM = [0.0, 1.1, 0.0, 11.0] 

ax.plot(x,np.sin(x-50.0),'b')

ax.set_xlim([XLIM[0], XLIM[1]])
ax.set_ylim([YLIM[0], YLIM[1]])

ax.set_xticks(np.arange(XLIM[0], XLIM[1], 0.2))
ax.set_yticks(np.arange(YLIM[0], YLIM[1]+0.1, 0.1)[:-1])

ax.grid(True,which='major',linestyle='solid')

ax.set_aspect((XLIM[1]-XLIM[0])/(YLIM[1]-YLIM[0]))

plt.show()

В результате на этом рисунке (в котором ранее определены y-пределы на левой стороне сбрасываются):

первая попытка близнеца

Теперь повторная попытка указать соотношение сторон не даст ожидаемого результата:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,1.6,50) + 50.0

fig = plt.figure()

ax = fig.add_subplot(111)
ax2 = ax.twinx()

XLIM = [50.0, 51.6]
YLIM = [0.0, 1.1, 0.0, 11.0] 

ax.plot(x,np.sin(x-50.0),'b')
ax2.plot(x,np.cos(x-50.0)*10.,'r')

ax.set_xlim([XLIM[0], XLIM[1]])
ax.set_ylim([YLIM[0], YLIM[1]])
ax2.set_ylim([YLIM[2], YLIM[3]])

ax.set_xticks(np.arange(XLIM[0], XLIM[1], 0.2))
ax.set_yticks(np.arange(YLIM[0], YLIM[1]+0.1, 0.1)[:-1])
ax2.set_yticks(np.arange(YLIM[2], YLIM[3]+1.0, 1.0))

ax.grid(True,which='major',linestyle='solid')

ax.set_aspect((XLIM[1]-XLIM[0])/(YLIM[1]-YLIM[0]))
ax2.set_aspect((XLIM[1]-XLIM[0])/(YLIM[3]-YLIM[2]))

plt.show()

Это производит:

попытка исправить соотношение сторон

Чего мне не хватает, чтобы создать сюжет, похожий на первый, но с двумя yось разных масштабов? Как определить соотношение сторон при использовании twinx?

1 ответ

Решение

Посмотрите на adjustable параметр осей. Это определяет, будут ли изменяться пределы данных или форма ограничивающего прямоугольника при изменении аспекта / пределов.

Обычно варианты "box" а также "datalim", но есть особый случай для общих осей. В вашем случае вы хотите adjustable='box-forced',

В качестве быстрого примера (я позволил себе немного упростить вещи, не стесняйтесь использовать отдельный set_foo методы, если они вам понятнее. Если вы берете этот маршрут, метод ax.set_adjustable.):

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,1.6,50) + 50.0

fig, ax = plt.subplots()
ax2 = ax.twinx()

XLIM = [50.0, 51.6]
YLIM = [0.0, 1.1, 0.0, 11.0]

ax.plot(x,np.sin(x-50.0),'b')
ax2.plot(x,np.cos(x-50.0)*10.,'r')

ax.set(adjustable='box-forced',
       xlim=XLIM, ylim=YLIM[:2],
       xticks=np.arange(XLIM[0], XLIM[1], 0.2),
       yticks=np.arange(YLIM[0], YLIM[1]+0.1, 0.1)[:-1],
       aspect=(XLIM[1]-XLIM[0])/(YLIM[1]-YLIM[0]))

ax2.set(adjustable='box-forced',
        ylim=YLIM[2:],
        yticks=np.arange(YLIM[2], YLIM[3]+1.0, 1.0),
        aspect=(XLIM[1]-XLIM[0])/(YLIM[3]-YLIM[2]))

ax.grid(True, which='major',linestyle='solid')

plt.show()

введите описание изображения здесь

Matplotlib 3.1 удаляет опцию "принудительное использование коробки". Решение Джо теперь даетValueError: 'box-forced' is not a valid value for adjustable; supported values are 'box', 'datalim'. Обходные пути можно найти в разделе "Определить соотношение сторон" при использовании twinx в новой версии matplotlib.

Другие вопросы по тегам