Seaborn Heatmap: подчеркнуть текст в ячейке - PullRequest
1 голос
/ 26 сентября 2019

Я делаю некоторый анализ данных в Python и использую Seaborn для визуализации.Seaborn очень хорошо работает для создания тепловых карт.

Я пытаюсь подчеркнуть максимальные значения для каждого столбца в моей тепловой карте.

Мне удалось правильно выделить текст в максимальных ячейках, сделав их курсив и полужирный .Тем не менее, я не нашел способа подчеркнуть это.

Это пример моего кода:


data_matrix = < extract my data and put them into a matrix >
max_in_each_column = np.max(data_matrix, axis=0)

sns.heatmap(data_matrix,
            mask=data_matrix == max_in_each_column,
            linewidth=0.5,
            annot=True,
            xticklabels=my_x_tick_labels,
            yticklabels=my_y_tick_labels,
            cmap="coolwarm_r")

sns.heatmap(data_matrix,
            mask=data_matrix != max_in_each_column,
            annot_kws={"style": "italic", "weight": "bold"},
            linewidth=0.5,
            annot=True,
            xticklabels=my_x_tick_labels,
            yticklabels=my_y_tick_labels,
            cbar=False,
            cmap="coolwarm_r")

Это мой текущий результат: My current heatmap, with maximum values for each column *italic* and **bold**

Конечно, я пытался использовать аргумент annot_kws={"style": "underlined"}, но, видимо, в Seaborn клавиша "style" поддерживает только значения "normal", "italic" или "oblique".

Есть ли обходной путь к этому?

1 Ответ

2 голосов
/ 26 сентября 2019

Да, вы можете обойти вашу проблему, используя текстовые команды внутри вашего текста.Основная идея заключается в том, что вы используете annot ключ seaborn.heatmap для назначения массива строк в качестве текстовых меток.Они содержат ваши значения данных + некоторые текстовые префиксы / суффиксы, позволяющие тексту сделать их жирным шрифтом / выделенным (курсивом) / подчеркнутым или чем-либо еще.

Пример (со случайными числами):

# random data
data_matrix = np.round(np.random.rand(10, 10), decimals=2)
max_in_each_column = np.max(data_matrix, axis=0)

# Activating tex in all labels globally
plt.rc('text', usetex=True)
# Adjust font specs as desired (here: closest similarity to seaborn standard)
plt.rc('font', **{'size': 14.0})
plt.rc('text.latex', preamble=r'\usepackage{lmodern}')

# remains unchanged
sns.heatmap(data_matrix,
            mask=data_matrix == max_in_each_column,
            linewidth=0.5,
            annot=True,
            cmap="coolwarm_r")

# changes here
sns.heatmap(data_matrix,
            mask=data_matrix != max_in_each_column,
            linewidth=0.5,
            # Use annot key with np.array as value containing strings of data + latex 
            # prefixes/suffices making the bold/italic/underline formatting
            annot=np.array([r'\textbf{\emph{\underline{' + str(data) + '}}}'
                            for data in data_matrix.ravel()]).reshape(
                np.shape(data_matrix)),
            # fmt key must be empty, formatting error otherwise
            fmt='',
            cbar=False,
            cmap="coolwarm_r")

plt.show()

Дальнейшее объяснение массива аннотаций:

# For all matrix_elements in your 2D data array (2D requires the .ravel() and .reshape() 
# stuff at the end) construct in sum a 2D data array consisting of strings 
# \textbf{\emph{\underline{<matrix_element>}}}. Each string will be represented by tex as 
# a bold, italic and underlined representation of the matrix_element
np.array([r'\textbf{\emph{\underline{' + str(data) + '}}}'
                        for data in data_matrix.ravel()]).reshape(np.shape(data_matrix))

Полученный график в основном соответствует желаемому:

enter image description here

...