Я пытаюсь использовать matplotlib с gridspec, чтобы создать подзаговор так, чтобы оси были расположены чтобы выглядеть как на рисунке ниже; цифра была взята из этого несвязанного вопроса а>.
Моя попытка воссоздать это расположение осей ниже. В частности, моя проблема в том, что оси не выровнены должным образом. Например, объект оси для синей гистограммы выше, чем объект оси для изображения с различными оттенками зеленого; кажется, что оранжевая гистограмма правильно выровнена по ширине, но я считаю это удачей. Как мне правильно выровнять эти оси? В отличие от исходного рисунка, я хотел бы добавить / заполнить дополнительное пустое пространство между осями, чтобы границы не пересекались; обозначение среза в приведенном ниже коде делает это путем добавления пустой строки / столбца. (Чтобы не делать этот пост длиннее, чем он должен быть, я не делал фигуры красивыми, играя с отметками оси и т.п.)
В отличие от исходного изображения, оси не идеально выровнены. Есть ли способ сделать это без использования ограниченного макета? Под этим я подразумеваю некую производную от fig, ax = plt.subplots(constrained_layout=True)
?
Код MWE для воссоздания моей фигуры ниже; обратите внимание, что не было разницы между ax.imshow(...)
и ax.matshow(...)
.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import Normalize
## initialize figure and axes
fig = plt.figure()
gs = fig.add_gridspec(6, 6, hspace=0.2, wspace=0.2)
ax_bottom = fig.add_subplot(gs[4:, 2:])
ax_left = fig.add_subplot(gs[:4, :2])
ax_big = fig.add_subplot(gs[:4, 2:])
## generate data
x = np.random.normal(loc=50, scale=10, size=100)
y = np.random.normal(loc=500, scale=50, size=100)
## get singular histograms
x_counts, x_edges = np.histogram(x, bins=np.arange(0, 101, 5))
y_counts, y_edges = np.histogram(y, bins=np.arange(0, 1001, 25))
x_mids = (x_edges[1:] + x_edges[:-1]) / 2
y_mids = (y_edges[1:] + y_edges[:-1]) / 2
## get meshed histogram
sample = np.array([x, y]).T
xy_counts, xy_edges = np.histogramdd(sample, bins=(x_edges, y_edges))
## subplot histogram of x
ax_bottom.bar(x_mids, x_counts,
width=np.diff(x_edges),
color='darkorange')
ax_bottom.set_xlim([x_edges[0], x_edges[-1]])
ax_bottom.set_ylim([0, np.max(x_counts)])
## subplot histogram of y
ax_left.bar(y_mids, y_counts,
width=np.diff(y_edges),
color='steelblue')
ax_left.set_xlim([y_edges[0], y_edges[-1]])
ax_left.set_ylim([0, np.max(y_counts)])
## subplot histogram of xy-mesh
ax_big.imshow(xy_counts,
cmap='Greens',
norm=Normalize(vmin=np.min(xy_counts), vmax=np.max(xy_counts)),
interpolation='nearest',
origin='upper')
plt.show()
plt.close(fig)
РЕДАКТИРОВАТЬ:
Можно инициализировать оси, явно задав width_ratios
и height_ratios
для каждой строки / столбца; это показано ниже. Это не влияет на вывод, но может я неправильно его использую?
## initialize figure and axes
fig = plt.figure()
gs = gridspec.GridSpec(ncols=6, nrows=6, figure=fig, width_ratios=[1]*6, height_ratios=[1]*6)
ax_bottom = fig.add_subplot(gs[4:, 2:])
ax_left = fig.add_subplot(gs[:4, :2])
ax_big = fig.add_subplot(gs[:4, 2:])