如何将热图设置为灰度并使用蒙版进行注释

问题描述 投票:0回答:2

我有一个矩阵A:

A = np.array([[ 0.        ,  0.00066748, -0.00097412, -0.00748846,  0.00305338],
       [-0.00157652,  0.        ,  0.0048117 ,  0.01069083, -0.0137888 ],
       [-0.00713212, -0.00170574,  0.        ,  0.00096385,  0.00212367],
       [-0.00186541,  0.00351104, -0.00590608,  0.        , -0.00448311],
       [-0.00929146,  0.00157808,  0.01300444, -0.00078593,  0.        ]])

使用以下代码创建一个热图,将空白(白色)分配给零值,将绿色分配给正值,将红色分配给负值:

import matplotlib.pyplot as plt
import seaborn as sns

rdgn = sns.diverging_palette(h_neg=10, h_pos=130, s=99, l=55, sep=3, as_cmap=True)
fig = plt.figure()
sns.heatmap(A, mask=(A == 0), cmap=rdgn, center=0)
plt.xticks(np.arange(0, 5, 1) + 0.5, [i + 1 for i in range(5)])
plt.yticks(np.arange(0, 5, 1) + 0.5, [i + 1 for i in range(5)], rotation=0)
plt.tick_params(axis='both', which='major', labelsize=10, labelbottom=False, bottom=False, top=False, labeltop=True)
plt.show()

我得到这个:

现在我的目标是将这张图片仅转换为灰度。一种方法是将较深的颜色分配给红色,将较浅的颜色分配给绿色,但我想强调从负值到正值的过渡,使零值与其他值非常不同,理想情况下将它们保留为空白。如果我尝试

fig = plt.figure()
sns.heatmap(A, mask=(A == 0), cmap = 'gray', center = 0)
plt.xticks(np.arange(0, 5, 1) + 0.5, [i + 1 for i in range(5)])
plt.yticks(np.arange(0, 5, 1) + 0.5, [i + 1 for i in range(5)], rotation=0)
plt.tick_params(axis='both', which='major', labelsize=10, labelbottom=False, bottom=False, top=False, labeltop=True)
plt.show()

我没有得到我想要的。使用

mask==0
我可以将零保留为空白,但这不会反映在右侧的颜色栏中。我想做的基本上是将颜色“拆分”为2:从纯黑到“半”灰色为负数(从最远到最近到零),白色为零,再次从白色到“半”灰色为正(从距离零最近到最远)。有办法实现这一点吗?我愿意接受任何有关如何解决问题的建议

python matplotlib seaborn heatmap grayscale
2个回答
2
投票

具有颜色渐变的想法是能够直接比较值。如果负/正使用不同的灰色阴影,则可能很难比较绝对值。

为什么不绘制绝对值并添加附加信息来区分负值和正值?

sns.heatmap(abs(A), annot=np.where(A<0, '−', ''), fmt='', cmap = 'gray_r', vmin=0)

或者:

sns.heatmap(abs(A), annot=np.select([A<0, A>0], ['−', '+'], ''),
            fmt='', cmap = 'gray_r', vmin=0)

使用符号/阴影线

您可以使用 unicode 符号来更轻松地可视化:

sns.heatmap(abs(A), annot=np.where(A<0, '▽', ''), fmt='',
            cmap = 'gray_r', vmin=0, annot_kws={'size': 30})

输出:

如果需要,您还可以添加阴影,如下所示此处

sns.heatmap(abs(A), cmap = 'gray_r', vmin=0)
zm = np.ma.masked_greater_equal(A, 0)
plt.pcolor(np.arange(A.shape[0])+0.5,
           np.arange(A.shape[1])+0.5,
           zm, hatch='//', alpha=0, zorder=3)

输出:


1
投票

根据@mozway的回答,我想出了这个:

plt.rcParams['hatch.linewidth'] = 0.15
x = np.arange(0, A.shape[1]+1, 1)
y = np.arange(0, A.shape[1]+1, 1)
zm = np.ma.masked_greater_equal(A, 0)
fig = plt.figure()
sns.heatmap(abs(A), cmap = 'gray_r', vmin=0)
plt.xticks(np.arange(0, 5, 1) + 0.5, [i + 1 for i in range(5)])
plt.yticks(np.arange(0, 5, 1) + 0.5, [i + 1 for i in range(5)], rotation=0)
plt.tick_params(axis='both', which='major', labelsize=10, labelbottom=False, bottom=False, top=False, labeltop=True)
plt.pcolor(x, y, zm, hatch='+', alpha  = 0)
plt.show()

这基本上是相同的解决方案,但不是放置 + 或 - 符号,而是在数字为负数的区域添加阴影线

我希望这可以帮助别人

© www.soinside.com 2019 - 2024. All rights reserved.