Seaborn热力图中自定义颜色调色板间隔

4
我希望您能够使用seaborn库绘制热力图。绘图函数如下:
def plot_confusion_matrix(data, labels, **kwargs):
    """Visualize confusion matrix as a heat map."""
    col_map = kwargs.get('color_palette', sns.light_palette('navy', n_colors=5, as_cmap=False))

    sns.heatmap(
        vmin=0.0,
        vmax=1.0,
        data=data,
        cmap=col_map,
        xticklabels=labels,
        yticklabels=labels,
        linewidths=0.75,
    )

然而,data的直方图如下所示:Histogram 现在我正在努力解决的问题是seaborn热图(如下所示)均匀分割颜色比例尺,因此大部分数据具有相同的颜色(因为数据不均匀分布)。
我无法找到如何设置某种间隔或边界以进行颜色级别的方法。
假设我有以下十六进制颜色值数组: ['#e5e5ff', '#acacdf', '#7272bf', '#39399f', '#000080'] 是否有一种方法设置颜色,例如 [(threshold_0, hex_0), (threshold_1, hex_1), ..., (threshold_n, hex_n)] 其中threshold_i是范围在[0,1)内的值?
感激任何帮助。
PS:当前热图示例:

enter image description here

3个回答

6

关于这份文档 在这里,您可以创建自己的颜色词典。 这些词典必须是rgb值,因此我编写了一个第一个测试函数来从Hex_colors和您期望的阈值生成rgb值:

def NonLinCdict(steps, hexcol_array):
    cdict = {'red': (), 'green': (), 'blue': ()}
    for s, hexcol in zip(steps, hexcol_array):
        rgb =matplotlib.colors.hex2color(hexcol)
        cdict['red'] = cdict['red'] + ((s, rgb[0], rgb[0]),)
        cdict['green'] = cdict['green'] + ((s, rgb[1], rgb[1]),)
        cdict['blue'] = cdict['blue'] + ((s, rgb[2], rgb[2]),)
    return cdict

hc = ['#e5e5ff', '#acacdf', '#7272bf', '#39399f', '#000080']
th = [0, 0.1, 0.5, 0.9, 1]

cdict = NonLinCdict(th, hc)
cm = mc.LinearSegmentedColormap('test', cdict)

plt.figure()
sns.heatmap(
        vmin=0.0,
        vmax=1.0,
        data=data,
        cmap=cm,
        linewidths=0.75)

生成如下内容:

enter image description here

还可以做更多事情(例如,离散跳跃),只需查看文档即可...但这应该回答了您最初的问题 - 这次包括了“自定义”...

但是,我必须加上我的个人意见:像这些一样拉伸的色标可能很“令人愉悦”,但人们应该注意它们不会误导观察者的眼睛。

希望这有所帮助。


谢谢你提供自定义颜色字典的方法,我之前并不知道这个。还有误导性调色板的概念。然而,最终你基本上做了和我一样的事情(请看我的解决方案),我认为这只是问题的一个小变通... 我很惊讶的是,在sns.heatplot中边界居然不能直接定义。+1 - CermakM

1

明知你问题中的“自定义”没有得到解答 - 或许这会在此期间有所帮助:

除了广泛应用于整个范围内平稳变化的众所周知的色图之外,还有一些更适合显示数据多个波段中的小差异的色图,例如 gist_ncar

另请参见 https://matplotlib.org/examples/color/colormaps_reference.html

enter image description here

创建于。
sns.heatmap(vmin=0.0, vmax=1.0, data=data,  cmap='gist_ncar', linewidths=0.75)

谢谢您的建议,我知道这样做会更好,可以更清楚地显示差异。但是有两个问题--第一,需要视觉上更加“美观”:),第二,由于我正在绘制的不是不同类别,所以最好只在色调上有所区别。 - CermakM

1
我能够找到一个(在我看来不是很干净的)解决方案,使用matplotlib.colors.LinearSegmentedColormap。代码如下:
# NOTE: jupyter notebook mode
%matplotlib inline

import seaborn as sns
from matplotlib.colors import LinearSegmentedColormap

boundaries = [0.0, 0.05, 0.1, 0.25, 0.5, 0.75, 0.9, 1.0]  # custom boundaries

# here I generated twice as many colors, 
# so that I could prune the boundaries more clearly
hex_colors = sns.light_palette('navy', n_colors=len(boundaries) * 2 + 2, as_cmap=False).as_hex()
hex_colors = [hex_colors[i] for i in range(0, len(hex_colors), 2)]

colors=list(zip(boundaries, hex_colors))

custom_color_map = LinearSegmentedColormap.from_list(
    name='custom_navy',
    colors=colors,
)

 sns.heatmap(
        vmin=0.0,
        vmax=1.0,
        data=data,
        cmap=custom_color_map,
        xticklabels=labels,
        yticklabels=labels,
        linewidths=0.75,
  )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接