Как настроить расположение цветовой полосы на тепловой карте Сиборна?

#python #seaborn #visualization #heatmap

Вопрос:

У меня есть следующий код для создания тепловой карты. Однако это создает наложение цветовой полосы и текста по правой оси. С текстом проблем нет, я хочу, чтобы он был такой длины.

Как я могу найти цветовую полосу справа/слева от тепловой карты без перекрытия? Я попытался использовать параметр «pad» в cbar_kws, но это не помогло.введите описание изображения здесь

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

PT=pd.DataFrame(np.random.randn(300,3), columns=list('ABC'))
miniPT=PT.iloc[:,:-1]
SMALL_SIZE = 8
MEDIUM_SIZE = 80
BIGGER_SIZE = 120    
plt.rc('font', size=MEDIUM_SIZE)          # controls default text sizes
plt.rc('axes', titlesize=MEDIUM_SIZE)     # fontsize of the axes title
plt.rc('axes', labelsize=MEDIUM_SIZE)    # fontsize of the x and y labels
plt.rc('xtick', labelsize=MEDIUM_SIZE)    # fontsize of the tick labels
plt.rc('ytick', labelsize=SMALL_SIZE)    # fontsize of the tick labels
plt.rc('legend', fontsize=MEDIUM_SIZE)    # legend fontsize
plt.rc('figure', titlesize=BIGGER_SIZE)  # fontsize of the figure title
plt.figure(figsize=(10, miniPT.shape[0]/5.2))
ax =sns.heatmap(miniPT, annot=False, cmap='RdYlGn')
for _, spine in ax.spines.items():
    spine.set_visible(True)
# second axis
asset_list=np.asarray(PT['C'])
asset_list=asset_list[::-1]
ax3 = ax.twinx()
ax3.set_ylim([0,ax.get_ylim()[1]])
ax3.set_yticks(ax.get_yticks())
ax3.set_yticklabels(asset_list, fontsize=MEDIUM_SIZE*0.6)
# colorbar
cbar = ax.collections[0].colorbar
cbar.ax.tick_params(labelsize=MEDIUM_SIZE)
 

Ответ №1:

Один из способов автоматической настройки перекрытия с помощью matplotlib заключается в явном создании подзаголовков: один для тепловой карты, а другой для цветовой панели. sns.heatmap cbar_ax= параметр s может быть установлен так, чтобы указывать на этот подзаголовок. gridspec_kws= необходимо установить относительные размеры. В конце plt.tight_layout() отрегулируйте все прокладки, чтобы все было хорошо подогнано.

Код вопроса содержит некоторые странные настройки (например, размер шрифта 80 огромен). Кроме того, 300 строк неизбежно приведут к перекрывающемуся тексту (размер шрифта должен быть настолько мал, чтобы неперекрывающийся текст не был читаем). Вот еще несколько упрощенных примеров кода:

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

PT = pd.DataFrame(np.random.randn(100, 3), columns=list('ABC'))
fig, (ax, cbar_ax) = plt.subplots(ncols=2, figsize=(10, len(PT) / 5.2), gridspec_kw={'width_ratios': [10, 1]})
sns.heatmap(PT.iloc[:, :-1], annot=False, cmap='RdYlGn', cbar_ax=cbar_ax, ax=ax)
for _, spine in ax.spines.items():
    spine.set_visible(True)
# second axis
asset_list = np.asarray(PT['C'])
ax3 = ax.twinx()
ax3.set_ylim(ax.get_ylim())
ax3.set_yticks(np.arange(len(PT)))
ax3.set_yticklabels(asset_list, fontsize=80)
# colorbar
cbar_ax.tick_params(labelsize=80)
plt.tight_layout()
plt.show()
 

Поскольку сюжет довольно большой, здесь вставлена только нижняя часть со ссылкой на полный сюжет.

sns.тепловая карта с пользовательским размещением цветовой панели

Вот как это выглядело бы с:

  • размер шрифта 80 (Обратите внимание, что размеры шрифта измеряются в «точках на дюйм», стандартные 72 точки на дюйм);
  • ширина рисунка 20 дюймов (вместо 10);
  • 300 строк
 
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

PT = pd.DataFrame(np.random.randn(300, 3), columns=list('ABC'))
fig, (ax, cbar_ax) = plt.subplots(ncols=2, figsize=(20, len(PT) / 5.2), gridspec_kw={'width_ratios': [15, 1]})
sns.heatmap(PT.iloc[:, :-1], annot=False, cmap='RdYlGn', cbar_ax=cbar_ax, ax=ax)
for _, spine in ax.spines.items():
    spine.set_visible(True)
# second axis
asset_list = np.asarray(PT['C'])
ax3 = ax.twinx()
ax3.set_ylim(ax.get_ylim())
ax3.set_yticks(np.arange(len(PT)))
ax3.set_yticklabels(asset_list, fontsize=80)
# colorbar
cbar_ax.tick_params(labelsize=80)
plt.tight_layout()
plt.show()
 

300 строк, размер шрифта 80

Комментарии:

1. Привет, Йоханк, спасибо за твое предложение. Однако это не помогает, так как мне нужно решение специально для моих настроек: мне нужно 300 строк на тепловой карте и размер текста 80. Также нет проблем с перекрывающимся текстом. Все, что я хочу, это переместить цветовую полосу, чтобы не было перекрытия с текстом. Я был бы рад получить любое другое решение 🙂

2. Ну, то, о чем вы просите, невозможно. Этот текст с размером шрифта 80 шире доступной ширины в 10 дюймов. Вы можете сделать более широкий сюжет, но все равно будете иметь крайнее перекрытие.

3. Как насчет того, чтобы поместить цветовую полосу в левой части тепловой карты? Возможно ли это? (Опять же, сохраняя 300 строк)

4. Вы можете установить цветовую полосу слева через fig, (cbar_ax, ax) = plt.subplots(ncols=2, figsize=..., gridspec_kw={'width_ratios': [1, 15]}) . Но в этом случае пространство будет так же занято. Вы все еще не можете поместить весь этот текст с размером шрифта 80 на 10 дюймов.

Ответ №2:

Мое решение состояло в том, чтобы в конечном итоге переместить цветовую полосу в левую сторону. Это код и выходные данные:

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

PT = pd.DataFrame(np.random.randn(300, 3), columns=list('ABC'))
fig, (ax0, ax1) = plt.subplots(ncols=2, figsize=(10, len(PT) / 5.2), gridspec_kw={'width_ratios': [15, 15]})
sns.heatmap(PT.iloc[:, :-1], annot=False, cmap='RdYlGn', cbar_ax=ax0, ax=ax1)
for _, spine in ax1.spines.items():
    spine.set_visible(True)
# second axis
asset_list = np.asarray(PT['C'])
ax3 = ax1.twinx()
ax3.set_ylim(ax1.get_ylim())
ax3.set_yticks(np.arange(len(PT)))
ax3.set_yticklabels(asset_list, fontsize=80)
# colorbar
ax0.tick_params(labelsize=80)
plt.tight_layout()
plt.show()