如何使用不规则间隔的自定义颜色图?

How to use a custom colormap with irregular intervals?

我正在尝试在 matplotlib 中使用不规则间隔的自定义颜色条。 但是当遵循 tutorial 并使用颜色条时,它被用作常规间隔颜色条。

如何 construct/use 不规则间隔的颜色条?

以下MWE:

我正在用 plt.matshow() 绘制各种数据,像这样:

testdf = pd.DataFrame([
    (7, 7.1, 8 , 9),
    (0, 1, 1.5, 2),
    (2.001, 3, 3.5, 4),
    (4.001, 5, 6, 6.9999),
], index=[0, 1, 2, 3], columns=('A', 'B', 'C', 'D'),)

plt.matshow(testdf)

但是,我只想突出显示某些数字,我想将其他数字分组,即我想要一个离散的自定义颜色条,而不是默认的连续颜色条。

幸运的是,matplotlib 文档 has just what I need。 所以,让我们设置这个颜色条:

fig, ax = plt.subplots(figsize=(6, 1))
fig.subplots_adjust(bottom=0.5)

cmap = (mpl.colors.ListedColormap(['red', 'green', 'blue', 'cyan'])
        .with_extremes(over='0.25', under='0.75'))

bounds = [1, 2, 4, 7, 8]
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
fig.colorbar(
    mpl.cm.ScalarMappable(cmap=cmap, norm=norm),
    cax=ax,
    boundaries=[0] + bounds + [13],  # Adding values for extensions.
    extend='both',
    ticks=bounds,
    spacing='proportional',
    orientation='horizontal',
    label='Discrete intervals, some other units',
)

看起来很棒! 1 到 2 的红色数字和 7 到 8 的蓝色数字以及 2 到 7 之间所有无趣内容的两大组。

所以,让我们使用它吧。

plt.matshow(testdf, cmap=cmap)
plt.colorbar()

...这不是我所期望的。 颜色条应该看起来像我之前构建的那个,没有规则间隔,因此第 0 行和第 1 行应该包含一个 black/grey 框 over/under,第 2 行应该全是绿色,第 3 行全是蓝色。

我该如何解决这个问题?我错过了什么?

正如 Jody Klymak 和 JohanC 在评论中指出的那样,norm 也需要传递到 matshow,即 plt.matshow(testdf, cmap=cmap, norm=norm).

但是,这不适用于我无法用我的颜色图传递更多参数的东西(或者我不知道如何这样做的地方......),例如在 sns.clustermap.

一个可能的解决方法是定义一个具有规则间隔的颜色图,其中许多间隔具有相同的颜色:

fig, ax = plt.subplots(figsize=(6, 1))
fig.subplots_adjust(bottom=0.5)

cmap = (mpl.colors.ListedColormap(['red',
                                   'green', 'green',
                                   'blue', 'blue', 'blue', 'blue',
                                   'cyan'])
                                   .with_extremes(over='0.25', under='0.75'))

bounds = [1, 2, 3, 4, 5, 6, 7, 8]
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
fig.colorbar(
    mpl.cm.ScalarMappable(cmap=cmap, norm=norm),
    cax=ax,
    boundaries=[0] + bounds + [13],  # Adding values for extensions.
    extend='both',
    ticks=bounds,
    spacing='proportional',
    orientation='horizontal',
    label='Discrete intervals, some other units',
)

结果

然后是

如您所见,它仍然与我在问题中的预期不同,但事实证明限制与我的预期不同,即区间 1, 2 意味着 >1, <2这很容易修复,如果你 know/expect 这种行为。