Imshow / Matshow сжимаются внутри осей - PullRequest
1 голос
/ 10 июля 2019

Я хочу построить матрицу чисел (как это делается через matshow / imshow).Затем я хочу нарисовать «на границах осей» некоторую функцию, относящуюся к осям.

Однако: я бы хотел, чтобы вывод matshow имел черную рамку, но, похоже, я не могуконтролировать это с помощью edge_color и line_width.Во-вторых, обе команды «сжимают» результирующие оси, так что оси + метки + метки все помещаются внутри осей.Однако это смещает сюжет с тем, что я хочу нарисовать на границах.

В частности, взгляните на следующую картинку.График плотности над matshow имеет ту же сетку, что и сетка x-axis из matshow, но он не охватывает ее полностью.Кроме того, он пропускает черный ящик вокруг matshow.

Как я могу добавить / исправить эти две функции?

incorrect output

Вот мой текущий фрагмент кода:

import numpy as np
from scipy.stats import norm
import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use('ggplot')
nX, nY = 50, 70
realXGrid = np.linspace(-0.5, 0.5, nX)
realYGrid = np.linspace(-1, 1, nY)
XX, YY = np.meshgrid(realXGrid, realYGrid, indexing='ij')
Z = XX * 3 - YY*5

# prepare figure/grid
fig5 = plt.figure()
widths = [1, 0.1, 0.1]
heights = [0.1, 1]
matAx = 3
caxAx = 5
spec5 = fig5.add_gridspec(ncols=3, nrows=2, width_ratios=widths,
                      height_ratios=heights, hspace=0, wspace=0)
axes = []
for row in range(2):
    for col in range(3):
        ax = fig5.add_subplot(spec5[row, col])
        axes.append(ax)

for i, ax in enumerate(axes):
    if i != matAx:
        ax.axis('off')
    else:
        ax.grid(False)
        ax.patch.set_edgecolor('black')
        ax.patch.set_linewidth('1')

# plot
cax = axes[matAx].imshow(Z, cmap='RdGy', origin='lower')
axes[matAx].axis('image')
fig5.colorbar(cax, ax=axes[caxAx], orientation='vertical', fraction=1)

xDensity = norm.pdf(realXGrid, scale=0.1)
yDensity = norm.pdf(realYGrid, scale=0.001)
axes[0].plot(realXGrid, xDensity)
axes[4].plot(yDensity, realYGrid) 
plt.show()

1 Ответ

1 голос
/ 10 июля 2019

Я бы порекомендовал построить изображение в реальных координатах данных. Это позволяет использовать те же лимиты для предельных распределительных участков.
Чтобы получить правильные интервалы, вы можете просто оставить равное соотношение сторон изображения.

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import norm

nX, nY = 50, 70
realXGrid = np.linspace(-0.5, 0.5, nX)
realYGrid = np.linspace(-1, 1, nY)
XX, YY = np.meshgrid(realXGrid, realYGrid, indexing='ij')
Z = XX * 3 - YY*5

# prepare figure/grid
fig5 = plt.figure()
widths = [1, 0.1, 0.1]
heights = [0.1, 1]
matAx = 3
caxAx = 5
spec5 = fig5.add_gridspec(ncols=3, nrows=2, width_ratios=widths,
                      height_ratios=heights, hspace=0, wspace=0)
axes = []
for row in range(2):
    for col in range(3):
        ax = fig5.add_subplot(spec5[row, col])
        axes.append(ax)

for i, ax in enumerate(axes):
    if i != matAx:
        ax.axis('off')
    else:
        ax.grid(False)
        ax.patch.set_edgecolor('black')
        ax.patch.set_linewidth('1')

# plot    
dx = np.diff(realXGrid)[0]
dy = np.diff(realYGrid)[0]
extent = [realXGrid[0]-dx/2, realXGrid[-1]+dx/2, 
          realYGrid[0]-dx/2, realYGrid[-1]+dx/2]
im = axes[matAx].imshow(Z, cmap='RdGy', origin='lower', aspect="auto",
                         extent=extent)
#axes[matAx].axis('image')
fig5.colorbar(im, ax=axes[caxAx], orientation='vertical', fraction=1)

xDensity = norm.pdf(realXGrid, scale=0.1)
yDensity = norm.pdf(realYGrid, scale=0.001)
axes[0].plot(realXGrid, xDensity)
axes[4].plot(yDensity, realYGrid) 
axes[0].set_xlim(*extent[:2])
axes[4].set_ylim(*extent[2:])
plt.show()

enter image description here

...