如何在保持颜色条范围的同时屏蔽 seaborn 热图

How to mask seaborn heatmap while keeping the colorbar range

我正在尝试使用 seaborn 热图创建方矩阵的可视化,其中所有元素的范围都在 0 和 1 之间。但是,我只想显示那些大于某个阈值(例如 0.5)和将其他值设置为0。此外,我想将colorbar的显示范围设置为0.5到1之间,但我不想将完整的colormap调整到0.5到1之间的范围,而是保持原始colormap范围。

例如,我附上两个我试过的例子:

第一个例子

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

# Make a random matrix composed of elements between 0 and 1
matrix=np.random.rand(20, 20)
mask_threshold=0.5
matrix_masked=np.zeros_like(matrix)
for i in range(len(matrix_masked)):
    for j in range(len(matrix_masked)):
        if matrix[i][j]<mask_threshold:
            matrix[i][j]=0
        else:
            matrix_masked[i][j]=matrix[i][j]

# Plot random matrix with seaborn heatmap, however I want to mask elements whose values are less than 0.5
# while keeping the colorbar range consistent
fig, ax=plt.subplots(figsize=(24, 20))
sns.heatmap(matrix, cmap="seismic", ax=ax, vmin=0, vmax=1)

cbar=ax.collections[0].colorbar
cbar.ax.tick_params(labelsize=30)
cbar.ax.yaxis.label.set_size(30)

cbar.outline.set_linewidth(1.0)
plt.tight_layout()
plt.show();

在第一个示例中,可视化矩阵与我最初想要的完全对应,但不是颜色栏,因为它的范围在 0 和 1 之间。因此,我尝试像第二个示例中那样更改颜色栏的范围。

第二个例子

# Plot random matrix with seaborn heatmap, however I want to mask elements whose values are less than 0.5
# while keeping the colorbar range consistent
fig, ax=plt.subplots(figsize=(24, 20))
sns.heatmap(matrix_masked, cmap="seismic", ax=ax, vmin=0, vmax=1)

cbar=ax.collections[0].colorbar
cbar.ax.set_ylim(0.5, 1.0)
cbar.ax.tick_params(labelsize=30)
cbar.ax.set_yticklabels(labels=[0.5, 0.6, 0.7, 0.8, 0.9, 1.0], weight="bold")
cbar.ax.yaxis.label.set_size(30)

cbar.outline.set_linewidth(1.0)
plt.tight_layout()
plt.show();

在第二个例子中,colorbar的范围确实像我想要的那样变化,但是图形和colorbar的高度不匹配,这是严重的问题。

我该如何解决这个问题?

你的 second example seems fine 在我这边,但这里有一个更简单的选择:

  1. Reds cmap 与 vmin=0.5 一起使用(无需更改 cbar 的 ylimyticklabels
  2. 使用 mask 参数自动屏蔽阈值(无需将它们清零)
  3. 设置用于在热图和颜色条上显示屏蔽值的“坏”和“下”颜色
matrix = np.random.default_rng(0).random(size=(20, 20))

cmap = plt.cm.get_cmap('Reds').copy()
cmap.set_bad('midnightblue')      # color of mask on heatmap
cmap.set_under('midnightblue')    # color of mask on cbar

sns.heatmap(matrix,
    cmap=cmap, vmin=0.5, vmax=1,  # set cbar range from 0.5 to 1
    mask=matrix < mask_threshold, # use "bad" color for thresholded values
    cbar_kws={'extend': 'min'})   # extend cbar to show "under" color