You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Matplotlib BoundaryNorm将等于上边界的值映射至set_over颜色问题

BoundaryNorm中1.0被识别为over值的问题分析

问题描述

我需要将0.1~1.0之间的值映射为离散颜色,小于0.1的用白色,大于1的用hotpink。但使用matplotlib.colors.BoundaryNorm时,发现1.0被映射到了set_over定义的hotpink,只有把1.0改成0.999999才能得到预期效果。同时疑惑文档中“大于等于上边界的值将被映射到最高索引”的描述是否有误。

测试代码

import matplotlib.colors as colors
from matplotlib.cm import get_cmap
import numpy as np
import matplotlib.pyplot as plt 
ncolors=11
vmin = 0.1
vmax = 1.0
cmap = get_cmap('RdYlBu_r',10).copy()
cmap.set_bad(color='gray',alpha=0)
cmap.set_under(color='white')
cmap.set_over(color='hotpink')
boundaries = list(np.arange(vmin, vmax, 0.1))+[vmax]

norm = colors.BoundaryNorm(boundaries, ncolors=ncolors, clip=False,extend='both')

print(norm(boundaries))

data=boundaries.copy()
data.insert(0,0)
data.append(1.5)

bar=np.repeat([data],5,axis=0).repeat(5,axis=1)
fig=plt.figure(figsize=(10,10))

img=plt.imshow(bar,cmap=cmap,norm=norm)
img.axes.get_xaxis().set_visible(False)
img.axes.get_yaxis().set_visible(False)

plt.colorbar(orientation='horizontal', extend='both')
plt.show()

问题原因

  1. BoundaryNorm的区间划分逻辑:当设置extend='both'时,BoundaryNorm的映射规则为:

    • 值小于第一个边界→under颜色(索引0)
    • 值落在[boundaries[i], boundaries[i+1})区间→对应中间颜色索引(i+1)
    • 值大于等于最后一个边界→over颜色(索引len(boundaries))
      你的边界最后一个值是1.0,所以1.0会被判定为大于等于上边界,直接映射到over颜色。文档描述的“最高索引”指的是未开启extend时的中间区间最高索引,开启extend后,大于等于上边界会被分配到额外的over索引,这是描述歧义导致的误解。
  2. 颜色数与区间数不匹配:你的边界列表有10个元素,对应9个离散区间,但你创建的colormap有10个颜色,颜色数和区间数不匹配,进一步加剧了映射混乱。

解决方案

调整边界和colormap的设置,让1.0落在最后一个离散区间内:

import matplotlib.colors as colors
from matplotlib.cm import get_cmap
import numpy as np
import matplotlib.pyplot as plt 

vmin = 0.1
vmax = 1.0
# 区间数是9,对应9个离散颜色
cmap = get_cmap('RdYlBu_r', 9).copy()
cmap.set_bad(color='gray', alpha=0)
cmap.set_under(color='white')
cmap.set_over(color='hotpink')

# 调整最后一个边界为略大于1.0的值,让1.0落在最后一个区间内
boundaries = list(np.arange(vmin, vmax, 0.1)) + [vmax + 1e-8]
# ncolors = 区间数 + 2(under和over)
norm = colors.BoundaryNorm(boundaries, ncolors=9+2, clip=False, extend='both')

print(norm(boundaries))

data = boundaries.copy()
data.insert(0, 0)
data.append(1.5)

bar = np.repeat([data],5,axis=0).repeat(5,axis=1)
fig = plt.figure(figsize=(10,10))

img = plt.imshow(bar, cmap=cmap, norm=norm)
img.axes.get_xaxis().set_visible(False)
img.axes.get_yaxis().set_visible(False)

plt.colorbar(orientation='horizontal', extend='both')
plt.show()

说明

  • 将colormap的颜色数改为9,和区间数(len(boundaries)-1=9)一致
  • 把最后一个边界设为1.0+1e-8,这样1.0会落在[0.9, 1.0+1e-8)区间内,被映射到最后一个离散颜色
  • 大于1.0+1e-8的值依然会被映射到over的hotpink颜色

内容的提问来源于stack exchange,提问作者Axel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 23:05:26