Seaborn热力图去除单元格之间的线条

4
我正在使用seaborn创建一个热图,并希望使用透明的颜色映射,因为背景中需要显示一张图片。目前,热图的创建已经很好地完成了,但是纵横线仍然可见,尽管热图的线宽已经设置为0.0。
以下是创建热图的代码:
ax = sns.heatmap(image, cmap="rocket_r", linewidths=0.0)
ax.collections[0].set_alpha(0.5)

image 是一个 64x64 的 numpy 数组。生成的热力图如下所示:热力图(很抱歉我没足够的声望来嵌入图片)。

问题出在单元格之间的细线上,奇怪的是,并非每个边缘都有这些线。

有人知道如何消除这些线吗?

非常感谢。


更新1(完整的工作示例):

image = np.array([[1, 1, 2, 2], [3, 3, 3, 3], [4, 5, 4, 5], [6, 6, 6, 6]])
ax = sns.heatmap(image, cmap="rocket_r", linewidths=0.0)
ax.collections[0].set_alpha(0.5)
plt.show()

这是热度图的结果:

这张热度图

您可以看到每列之间有细线,但第一行和第二行之间没有任何线。


你能否创建一个带有完整代码的小数据集? - Scott Boston
@ScottBoston 我刚刚添加了一个可工作的代表性代码示例,您可以看到有些行被创建而其他行则没有。 - Maximilian Speicher
2个回答

5

这些线是半透明补丁的重叠,无法完美对齐像素网格。

Alpha混合

一种选择是不使用透明度,而是使用Alpha混合创建不透明颜色。

import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
import numpy as np
import seaborn as sns

def get_alpha_blend_cmap(cmap, alpha):
    cls = plt.get_cmap(cmap)(np.linspace(0,1,256))
    cls = (1-alpha) + alpha*cls
    return ListedColormap(cls)

image = np.array([[1, 1, 2, 2], [3, 3, 3, 3], [4, 5, 4, 5], [6, 6, 6, 6]])
ax = sns.heatmap(image, cmap=get_alpha_blend_cmap("rocket_r", 0.5), linewidths=0.0)

plt.show()

输入图像说明

显而易见的好处是,色条与热力图具有相同的颜色。

增加dpi

如果上述方法不可行,您可以在保存时增加dpi。

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

image = np.array([[1, 1, 2, 2], [3, 3, 3, 3], [4, 5, 4, 5], [6, 6, 6, 6]])
ax = sns.heatmap(image, cmap="rocket_r", linewidths=0.0, edgecolor="none", alpha=0.5)
plt.savefig("test.png", dpi=1000)

在此输入图像描述

当然,这不会对屏幕上显示的图像产生任何影响。

imshow

最后,考虑不使用seaborn,而是使用matplotlib的imshow绘制。

import matplotlib.pyplot as plt
import seaborn as sns
plt.style.use("seaborn-dark")
plt.rcParams["axes.facecolor"] = "white"
import numpy as np

image = np.array([[1, 1, 2, 2], [3, 3, 3, 3], [4, 5, 4, 5], [6, 6, 6, 6]])
im = plt.imshow(image, cmap="rocket_r", alpha=0.5)
plt.colorbar(im)
plt.gca().set(xticks=(range(image.shape[1])),yticks=(range(image.shape[0])))
plt.show()

enter image description here


谢谢你的解决方案。它按照我的要求删除了不需要的行。然而,我遇到了下一个问题。正如最初的问题所述,我正在尝试在背景中显示一张图像(.png,借助于plt.imshow())。因此,热力图需要是透明的。但是,使用不透明的颜色时,背景不可见。我通过将图像移动到前景并赋予其alpha值来“修复”这个问题。但是,这样做后,色图不再匹配真实的颜色。是否可以以同样的方式修改色条?或者还有其他解决方法吗? - Maximilian Speicher
我在答案中添加了另外两个选项。 - ImportanceOfBeingErnest
非常感谢。这两种解决方案都可以很好地解决我的问题。但是我会坚持使用seaborn(第二种解决方案),因为外观更加清晰。 - Maximilian Speicher
“Cleaner”是什么意思?在最后的解决方案中,不干净的边缘问题都消失了吗? - ImportanceOfBeingErnest
我对matplotlib解决方案的问题是色图中的水平线。我现在已经成功地将它们移除了。 我的最终解决方案如下:
  1. 使用第一选项绘制热力图,并根据混合颜色添加色图
  2. 清除图形的轴
  3. 使用选项3绘制热力图,但不创建热力图 按照这个步骤进行操作会得到我想要的精确输出。
- Maximilian Speicher

0

我刚遇到了这个问题。我需要将图形上传到Overleaf,所以我不喜欢dpi解决方案。根据OP的解决方案,我想到了以下方法:

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

image = np.array([[1, 1, 2, 2], [3, 3, 3, 3], [4, 5, 4, 5], [6, 6, 6, 6]])
ax = sns.heatmap(image, cmap="rocket_r", linewidths=0.1)
colors = ax.collections[0].get_facecolors()
ax.collections[0].set_edgecolors(colors)
plt.imshow()

这个想法是在每个单元格周围创建一个细边缘,其颜色与单元格的面颜色相同。这样可以去除线条,而不改变原始单元格的颜色。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接