Как использовать twinx с топором, созданным с помощью make_axes_locatable
Я хочу построить изображение и цветовую шкалу с соответствующей гистограммой ниже. Две оси изображения и гистограмма должны иметь одинаковую ширину. Кроме того, цветовая полоса должна быть такой же высоты, как изображение. Часть, которая является (и не должна) быть сложной, состоит в наложении графика кумулятивной гистограммы с процентным содержанием каждого бина по отношению к размеру данных.
На данный момент я получил что-то вроде этого:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
data = np.random.normal(0,2,size=(100,100))
fig = plt.figure()
ax = fig.add_subplot(2,1,1)
im = ax.imshow(data,cmap="bone")
divider = make_axes_locatable(ax)
ax1 = divider.append_axes("right", size="5%", pad=0.05)
plt.colorbar(im,cax=ax1)
ax2 = divider.append_axes("bottom",size="100%",pad = 0.3)
n,bins,patches = ax2.hist(data.flatten(),bins=20)
ax3 = ax2.twinx()
ax3.plot(bins[:-1],np.cumsum(n*100/np.size(data)),lw=2)
plt.show()
Все идет гладко, пока я не попытаюсь использовать twinx на ax2 (чтобы построить мое кумулятивное распределение на ax3 с другой шкалой y). Результирующая ось вместо ax2 оборачивает все оси фигуры.
Я не понимаю, что не так и как я могу это исправить.
1 ответ
Это сложный вопрос. Проблема в том, что axes_grid1
Инструментарий предназначен для позиционирования осей во время рисования. Очевидно, он сначала рисует двойную ось, и только после этого перемещает оси в соответствии с делителем.
Что еще хуже, так это то, что вы хотите, чтобы оси с одинаковым соотношением сторон были привязаны к осям с неравным соотношением, что делает невозможным использование AxisGrid
,
В то время как любая двойная комбинация равный + неравный или равный + близнец или неравный + близнец будет работать так или иначе, все три слишком много.
Таким образом, решение, вероятно, состоит в том, чтобы начать с нуля, просто поместив оси на холст и только в самом конце переместите / измените их размер. Это можно сделать с помощью прослушивателя событий, подключенного к функции, которая получает положение осей с одинаковым аспектом и соответственно изменяет размеры двух других осей.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
data = np.random.normal(0,2,size=(100,100))
fig = plt.figure()
ax = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
im = ax.imshow(data,cmap="bone")
n,bins,patches = ax2.hist(data.flatten(),bins=20)
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)
plt.colorbar(im, cax=cax)
ax3 = ax2.twinx()
ax3.plot(bins[:-1],np.cumsum(n*100/np.size(data)),lw=2, c=plt.cm.bone(0.4))
def resize(event):
axpos = ax.get_position()
axpos2 = ax2.get_position()
newpos = [axpos.x0, axpos2.y0, axpos.width, axpos2.height]
ax2.set_position(newpos)
ax3.set_position(newpos)
cid = fig.canvas.mpl_connect('draw_event', resize)
cid2 = fig.canvas.mpl_connect('resize_event', resize)
#if you want to save the figure, trigger the event manually
save=False
if save:
fig.canvas.draw()
resize()
plt.savefig(__file__+".png")
plt.show()