Ширина тепловой карты Seaborn не совпадает при использовании дополнительных графиков - PullRequest
2 голосов
/ 21 июня 2020

Я пытаюсь настроить ширину моего второго подзаголовка (сумма столбцов с двоичным cmap) до первого.

До сих пор мне удавалось сделать это только случайным образом выбирая другой размер фиг, но каждый раз Я пытаюсь повторно использовать код в наборе данных разного размера. Я всегда придумываю что-то вроде рисунка ниже (вторая тепловая карта всегда шире первой).

Мне что-то не хватает, чтобы настроить вторую автоматически?

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

import matplotlib.pyplot as plt    
import seaborn as sns   
import pandas as pd
test = pd.DataFrame({'user': ['Bob', 'Bob', 'Bob','Janice','Janice','Fernand','Kevin','Sidhant'], 
                     'tag' : ['enfant','enfant','enfant','femme','femme','jeune','jeune','jeune'],
                   'income': [3, 5, 1,14,8,10,13,17]})
  
# specify font sizes for later:

titlesize= 30
ticklabel = 23
legendlabel = 23

# Generate custom diverging colormaps:

cmap = sns.color_palette("ch:18,-.1,dark=.3",  6)
cmap2 = sns.color_palette("binary",  6)

# Preparing data for the heatmap:

heatmap1_data = pd.pivot_table(test, values='income', 
                                 index=['user'], 
                                 columns='tag')
heatmap1_data = heatmap1_data.reindex(heatmap1_data.sum().sort_values(ascending=False).index, axis=1)

# Creating figure:

fig, (ax1, ax2) = plt.subplots(2,1,figsize=(10,15))

# First subplot:

sns.heatmap(heatmap1_data, ax= ax1, cmap=cmap,square=True, linewidths=.5, annot=True, cbar = False,annot_kws={"size": legendlabel} )

# Cosmetic first subplot:

ax1.xaxis.tick_top()
ax1.tick_params(labelsize= ticklabel, top = False)
ax1.set_xlabel('')
ax1.set_ylabel('')
ax1.set_xticklabels(heatmap1_data.columns,rotation=90)
ax1.set_yticklabels(heatmap1_data.index,rotation=0)
ax1.set_title("Activités par agence et population vulnérable", size= titlesize, pad=20)

# Second subplot (column sum at the bottom):

sns.heatmap((pd.DataFrame(heatmap1_data.sum(axis=0))).transpose().round(1), ax=ax2, square=True, fmt='g', linewidths=.5, annot=True, cmap=cmap2 , cbar=False, xticklabels=False, yticklabels=False, annot_kws={"size": legendlabel})
ax2.set_xlabel("Nombre d'activités", size = ticklabel, labelpad = 5)

# More cosmetic:

ax1.set_title("Title", size= titlesize, pad=35)
ax1.set_xlabel('')
ax1.set_ylabel('')
plt.tick_params(labelsize= ticklabel,left=False, bottom=False)
plt.xticks(rotation=60)
ax1.spines['bottom'].set_color('#dfe1ec')
ax1.spines['left'].set_color('#dfe1ec')
ax1.spines['top'].set_color('#dfe1ec')
ax1.spines['right'].set_color('#dfe1ec')
plt.tight_layout()

plt.show()

1 Ответ

1 голос
/ 21 июня 2020

Проблема использует square=True в sns.heatmap. Так как аспект крысы ios двух подзаговоров широкий и высокий, способ «возведения в квадрат» для каждого из них различен. Для первого он стал тоньше, а для второго - короче. Это сделано таким образом, чтобы соответствовать ограничениям размеров осей вашего подзаголовка, которые по умолчанию определены как равные при вызове plt.subplots.

Один из способов обойти это - определить аспект крысы ios ваших двух осей должно отличаться и соответствовать форме ваших данных. Это не сработает в 100% случаев, но будет работать в большинстве случаев. Вы можете использовать ключевое слово gridspec_kw и определить словарь с помощью 'height_ratios' в вызове plt.subplots.

fig, (ax1, ax2) = plt.subplots(2,1, figsize=(10,15), gridspec_kw={'height_ratios':[5, 1]})

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

...