Подтвердить что ты не робот

Как сделать квадрат тепловой карты в Seaborn FacetGrid

Я использую класс Seaborn FacetGrid для построения набора матриц с использованием функции heatmap, также из Seaborn. Однако я не могу настроить соотношение сторон этих подзаговоров. Вот пример:

import seaborn as sns
import numpy as np
import pandas as pd

# Generate a set of sample data
np.random.seed(0)
indices = pd.MultiIndex.from_product((range(5), range(5), range(5)), names=('label0', 'label1', 'label2'))
data = pd.DataFrame(np.random.uniform(0, 100, size=len(indices)), index=indices, columns=('value',)).reset_index()

def draw_heatmap(*args, **kwargs):
    data = kwargs.pop('data')
    d = data.pivot(index=args[1], columns=args[0], values=args[2])
    sns.heatmap(d, **kwargs)

fg = sns.FacetGrid(data, col='label0')
fg.map_dataframe(draw_heatmap, 'label1', 'label2', 'value', cbar=False)

Это создает это изображение:

горизонтальный массив графиков

Обратите внимание, что элементы матричных графиков являются прямоугольными, а не квадратными. Если бы я делал один сюжет (без FacetGrid), я мог бы передать опцию square=True на sns.heatmap, чтобы сделать квадрат сюжета. Однако, если я помещаю это в аргументы map_dataframe, я получаю этот результат:

fg = sns.FacetGrid(data, col='label0')
fg.map_dataframe(draw_heatmap, 'label1', 'label2', 'value', cbar=False, square=True)

массив графиков с квадратной опцией

Похоже, что оси слишком велики для данных, хотя соотношение сторон по умолчанию для FacetGrid равно 1. (И явно установка aspect=1 при построении FacetGrid не помогает.)

Есть ли способ исправить это?

4b9b3361

Ответ 1

Когда вы устанавливаете аргумент aspect FacetGrid не только осевым пределом, но и размеры и расположение меток и названий осей также учитываются для вычисления правильной геометрии оси. Поэтому тепловые карты представляют собой прямоугольники.

Чтобы настроить квадратичную тепловую карту и ось, вы можете вручную установить положение ограничивающей рамки оси с помощью функции set_bbox.

Другой способ немного сложнее. Функция ax.set_aspect со вторым аргументом box_forced попытается отрегулировать тепловую карту и ось. Однако, чтобы полностью удалить оставшиеся серые границы, вы можете скрыть их, установив цвет фона оси в соответствии с цветом лица лица, как здесь:

import seaborn as sns
import numpy as np
import pandas as pd
import matplotlib.pylab as plt

# Generate a set of sample data
np.random.seed(0)
indices = pd.MultiIndex.from_product((range(5), range(5), range(5)),
 names=('label0', 'label1', 'label2'))
data = pd.DataFrame(np.random.uniform(0, 100, size=len(indices)),
 index=indices, columns=('value',)).reset_index()

def draw_heatmap(*args, **kwargs):
    data = kwargs.pop('data')
    d = data.pivot(index=args[1], columns=args[0], values=args[2])
    sns.heatmap(d, **kwargs)

fg = sns.FacetGrid(data, col='label0')
fg.map_dataframe(draw_heatmap, 'label1', 'label2', 'value', cbar=False, square = True)
# get figure background color
facecolor=plt.gcf().get_facecolor()
for ax in fg.axes.flat:
    # set aspect of all axis
    ax.set_aspect('equal','box-forced')
    # set background color of axis instance
    ax.set_axis_bgcolor(facecolor)
plt.show()

Результат:

введите описание изображения здесь

Ответ 2

Вы можете использовать параметр square=True заменив это в своем коде:

fg.map_dataframe(draw_heatmap, 'label1', 'label2', 'value', cbar=False, square=True)