seaborn 热图中的调色板

color palette in seaborn heatmap

当使用 LinearSegmentedColormap 时,Matplotlib 文档提到了关于参数 colors that

colors: array-like of colors or array-like of (value, color). If only colors are given, they are equidistantly mapped from the range [0,1]; i.e. 0 maps to colors[0] and 1 maps to colors[-1]. If (value, color) pairs are given, the mapping is from value to color. This can be used to divide the range unevenly.

我有以下颜色 ['crimson', 'brown', 'lime', 'brown', 'crimson'] 我想不均匀地划分范围这样:

(-1, -0.5) : 'crimson'

(-0.5, -0.15) : 'brown'

(-0.15, 0.15) : 'lime'

(0.15, 0.5) : 'brown'

(0.5, 1) : 'crimson'

我尝试以以下格式传递 colors 参数:[(-1, 'crimson'), (-0.5, 'brown), (-0.15, 'lime'), (0.15, 'brown), (0.5, 'crimson')] 但出现错误。我错过了什么吗?

要实现所描述的颜色分割,您可以组合 LinearSegmentedColormap.from_list('', colors, len(colors)) with a BoundaryNorm。请注意,5 种颜色需要 6 个边界。

LinearSegmentedColormap 使用 (value, color) 对似乎有点麻烦,因为值需要规范化以严格从 0 到 1。如果您需要连续范围,这将更适合颜色并希望在特定位置(而不是特定范围)设置特定颜色。

from matplotlib import pyplot as plt
from matplotlib.colors import LinearSegmentedColormap, BoundaryNorm
import numpy as np

bounds = [-1, -0.5, -0.15, 0.15, 0.5, 1]
colors = ['crimson', 'brown', 'lime', 'brown', 'crimson']
cmap = LinearSegmentedColormap.from_list('', colors, N=len(colors))
norm = BoundaryNorm(bounds, ncolors=len(colors), )

x = np.random.uniform(0, 1, 100)
y = np.random.uniform(-1, 1, 100)
plt.scatter(x, y, c=y, cmap=cmap, norm=norm)
plt.colorbar()
plt.show()

请注意,您可以使用 plt.colorbar(spacing='proportional') 为更大的范围显示更大的颜色块。默认值为 spacing='uniform',每种颜色均等 space。

PS:关于新问题,可以使用 LinearSegmentedColormap(value, color) 列表创建自定义平滑颜色图并设置额外边界。

from matplotlib import pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
import numpy as np

bounds = [-1, -0.5, -0.499, -0.15, -0.149, 0.0, 0.149, 0.15, 0.499, 0.5, 1]
colors = ['crimson', 'crimson', 'brown', 'brown', 'limegreen', 'lime', 'limegreen', 'brown', 'brown', 'crimson', 'crimson']

norm = plt.Normalize(bounds[0], bounds[-1])
cmap = LinearSegmentedColormap.from_list('', [(norm(b), c) for b, c in zip(bounds, colors)], N=256)

x = np.random.uniform(0, 1, 100)
y = np.random.uniform(-1, 1, 100)
plt.scatter(x, y, c=y, cmap=cmap, norm=norm)
plt.colorbar()
plt.show()