在 matplotlib 和 seaborn 中修改颜色条

modifying colorbar in matplotlib and seaborn

我正在尝试保存使用 seaborn 生成的图像。该图像是 4x4 混淆矩阵('confmat' np.array)。我了解到,当我以矢量格式保存图像时,某些查看器会出现问题,导致颜色条上出现白线,引自 matplotlib 参考:

It is known that some vector graphics viewer (svg and pdf) renders white gaps between segments of the colorbar. This is due to bugs in the viewers not matplotlib. As a workaround the colorbar can be rendered with overlapping segments:

cbar = colorbar()

cbar.solids.set_edgecolor("face")

draw()

但是,我无法按照建议进行操作。

这是我所做的:

import seaborn as sns
import matplotlib.pyplot as plt

cmap=plt.cm.Blues

fig, ax = plt.subplots()
    
ax = sns.heatmap(confmat, annot=True, cmap=cmap)
ax.set_title('title')
ax.tick_params(
    axis='both',          # changes apply to the x-axis
    which='both',      # both major and minor ticks are affected
    bottom='off',      # ticks along the bottom edge are off
    top='off',         # ticks along the top edge are off
    labelbottom='off',  # labels along the bottom edge are off
    labelleft='off',
    right='off')

fig.savefig('confusion_matrix.svg', format='svg')

我尝试使用

获取颜色条
cbar = ax.colorbar()

但是报错AttributeError: 'AxesSubplot' object has no attribute 'colorbar'.

我搜索了解决方案并在这里发现了一些建议使用 plt.imshow() 来获取颜色条对象的问题,但我对我现在正在做的事情完全感到困惑。 有人可以建议,如果可能的话,解释为什么,实现 matplotlib 文档为 colorbar 提供的解决方案吗?

按照 matplotlib 文档中的建议将 colorbar 更改为 cb.solid.set_edgecolor("face") 似乎有点麻烦,以确保颜色条上的元素之间没有白线。我认为 seaborn 的设计假设你应该能够通过传递 kwargs(热图中的cbar_kws)来完成你需要的一切。例如,您可以将 cb_kwargs 传递给 sns.heatmap 函数 cbar_kws={"drawedges": "False"} 但不幸的是,这并不能解决问题。

由于 Seaborn Heatmap 只有 returns 一个轴手柄,在其上绘制了 heatplotcolorbar,您没有直接访问源代码中的可映射对象 cbar。因此,您无法应用此 hack。

一个解决方案是使用 pcolormeshcolorbar 绘制它。我认为 seaborn 实际上重新定义了 matplotlib 样式,所以看起来应该是一样的,

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

cmap=plt.cm.Blues

fig, ax = plt.subplots()
confmat = np.random.rand(4, 4)

cb = ax.pcolormesh(confmat, cmap=cmap)

ax.set_title('title')
ax.tick_params(
    axis='both',          # changes apply to the x-axis
    which='both',      # both major and minor ticks are affected
    bottom='off',      # ticks along the bottom edge are off
    top='off',         # ticks along the top edge are off
    labelbottom='off',  # labels along the bottom edge are off
    labelleft='off',
    right='off')

cbar = plt.colorbar(cb)
cbar.solids.set_edgecolor("face")
plt.draw()

fig.savefig('confusion_matrix.svg', format='svg')

我的结果看起来是在放大时去掉了白线。

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

x = np.random.randn(10, 10)

f, ax = plt.subplots()
sns.heatmap(x)
cbar_ax = f.axes[-1]
cbar_solids = cbar_ax.collections[0]
cbar_solids.set_edgecolor("face")
f.savefig("heatmap.svg")