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 на основе размеров изображения, чтобы не нарушать геометрию пикселей. В этой комбинации сетка остаётся опрятной, цветовые шкалы корректно выравниваются с осями, а изменение размера фигуры больше не приводит к хаотичным пропорциям.