Как использовать 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()

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