2025, Dec 06 00:02
Как выровнять pcolor и линейные графики в Matplotlib: используем layout=compressed
Смешиваете pcolor и линейные графики в Matplotlib? Узнайте, как добиться одинакового размера осей и квадратных пикселей с layout=compressed и цветовых шкал.
Когда вы совмещаете изображения pcolor из Matplotlib с обычными линейными графиками в одной сетке, добиться единообразных размеров осей и соотношений сторон бывает непросто. Даже при включённом constrained_layout линии могут выглядеть слишком широкими или слишком высокими, а их высота порой привязывается к соседним цветовым шкалам, а не к самим цветовым картинкам. Цель проста: все оси должны иметь одинаковый след на странице, пиксели pcolor — оставаться квадратными, а цветовые шкалы — аккуратно выравниваться, не нарушая сетку.
Воспроизводим проблему
Следующий фрагмент строит сетку 6×2 со смешанным содержимым. Оси pcolor фиксируют соотношение сторон, чтобы пиксели были квадратными; ожидается, что линейные графики подстроятся под тот же аспект, но constrained_layout в итоге даёт неодинаковые ширины и высоты.
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
# Синтетические данные
img_w, img_h = 265, 200
heat_img = np.random.rand(img_h, img_w)
series_vals = np.random.rand(40)
# Сетка с constrained_layout
fig, axs = plt.subplots(6, 2, figsize=(8, 11), constrained_layout=True)
[[slot1, slot2], [slot3, slot4], [slot5, slot6], [slot7, slot8], [slot9, slot10], [slot11, slot12]] = axs
for pane in [slot1, slot2, slot3, slot5, slot7, slot9, slot11]:
pic = pane.pcolor(heat_img, vmin=0, vmax=1)
plt.colorbar(pic, ax=pane, label='z', fraction=0.046, pad=0.04)
pane.grid(False)
pane.set_aspect(img_h / img_w)
pane.set_xlabel('x')
pane.set_ylabel('y')
pane.invert_yaxis()
for pane in [slot4, slot6, slot8, slot10, slot12]:
pane.plot(np.arange(len(series_vals)), series_vals, color='blue', linewidth=2)
pane.set_xlabel('index')
pane.set_ylabel('value')
Что на самом деле происходит
Оси pcolor навязывают фиксированное соотношение сторон, чтобы пиксели изображения оставались квадратными. В смешанной сетке constrained_layout пытается согласовать требования по размеру для осей и их цветовых шкал. Итог сильно зависит от размера фигуры: одни линейные графики оказываются шире своих соседей pcolor, а их высота порой выравнивается по цветовым шкалам, а не по самим pcolor-картинкам. На практике сетка выглядит неровной, а простая подстройка figsize меняет результат, но не гарантирует единообразия.
Ваши pcolor-графики имеют фиксированное соотношение сторон. Используйте layout='compressed', чтобы с этим справиться.
Решение
Переключитесь на режим сжатого макета. Он рассчитан на сетки с осями фиксированного соотношения сторон — как раз тот случай, когда вы смешиваете pcolor и линейные графики и хотите сохранить квадратные пиксели. С layout='compressed' Matplotlib раскладывает оси и цветовые шкалы так, чтобы они имели согласованные размеры и при этом сохраняли заданный аспект.
import matplotlib.pyplot as plt
import numpy as np
# Синтетические данные
img_w, img_h = 265, 200
heat_img = np.random.rand(img_h, img_w)
series_vals = np.random.rand(40)
# Сетка с layout='compressed'
fig, axs = plt.subplots(6, 2, figsize=(8, 11), layout='compressed')
[[cell1, cell2], [cell3, cell4], [cell5, cell6], [cell7, cell8], [cell9, cell10], [cell11, cell12]] = axs
for axis in [cell1, cell2, cell3, cell5, cell7, cell9, cell11]:
im = axis.pcolor(heat_img, vmin=0, vmax=1)
plt.colorbar(im, ax=axis, label='z', fraction=0.046, pad=0.04)
axis.grid(False)
axis.set_aspect(img_h / img_w)
axis.set_xlabel('x')
axis.set_ylabel('y')
axis.invert_yaxis()
for axis in [cell4, cell6, cell8, cell10, cell12]:
axis.plot(np.arange(len(series_vals)), series_vals, color='blue', linewidth=2)
axis.set_xlabel('index')
axis.set_ylabel('value')
plt.show()
Зачем это важно
При подготовке дашбордов, отчётов или публикаций согласованность подграфиков не менее важна, чем сами данные. Смешанное содержимое встречается часто, и pcolor-изображения нередко задают визуальный ритм страницы. Аккуратное выравнивание всего, включая цветовые шкалы, повышает читабельность и предотвращает неверные сопоставления из-за неодинаковых размеров осей.
Выводы
Если в вашей сетке есть pcolor-изображения с квадратными пикселями и вы хотите, чтобы обычные графики совпадали с их площадью, используйте layout='compressed'. Сохраняйте set_aspect на основе размеров изображения, чтобы не нарушать геометрию пикселей. В этой комбинации сетка остаётся опрятной, цветовые шкалы корректно выравниваются с осями, а изменение размера фигуры больше не приводит к хаотичным пропорциям.