【问题标题】:How to use a custom colormap with irregular intervals?如何使用不规则间隔的自定义颜色图?
【发布时间】:2025-12-17 00:30:02
【问题描述】:

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

如何构建/使用不规则间隔的颜色条?

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 行应该包含一个黑色/灰色框,用于上/下,第 2 行应该是全绿色,第 3 行全是蓝色。

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

【问题讨论】:

  • 您需要将边界规范以及颜色图传递给matshow,以便 Matplotlib 知道如何将您的数据映射到颜色图。 matplotlib.org/stable/api/_as_gen/…
  • “使用它”plt.matshow(testdf, cmap=cmap, norm=norm)
  • 那行得通。我知道这可能是一个愚蠢的疏忽。您可以将其发布为答案吗?

标签: python matplotlib colorbar


【解决方案1】:

正如 Jody Klymak 和 JohanC 在 cmets 中指出的那样,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 很容易修复,如果您知道/期望这种行为。

【讨论】:

    最近更新 更多