关于python:Matplotlib:将渐变色图与列出的色图结合

Matplotlib: combine gradient colormap with listed colormap

我有一些计算得出的(0,1)(注意不包括两个数字)值的DataFrame。

然后,我用0填充了一些缺失值。

我想为热图创建以下颜色图:

  • 如果数据丢失(== 0):热图中的白色(仅一种白色)。
  • 如果数据低于阈值(例如0 <数据<0.5):浅色(仅一种浅色)。
  • 如果数据高于阈值:红色(或其他任何无关紧要的)颜色的渐变色图。
  • 他们在这里的关键是我希望1和2具有完全的灰色和白色。我不希望在阈值以下的值和阈值以上的值之间出现任何渐变。

    我已经看到了有关合并两个颜色图的问题:合并两个matplotlib颜色图,但我真的不明白该代码在哪个位置将负值映射到不同的颜色图,或者如何使第二个颜色图成为非渐变。

    数据仅出于示例目的:

    1
    2
    data = np.random.rand(10,10) * 2 - 1.3
    data[data < 0] = 0

    ListedColormap

    1
    2
    3
    4
    5
    6
    7
    cmap = colors.ListedColormap(['gray', 'white', 'red'])
    bounds = [0, 0.0001, 0.1, 1.0]
    norm = colors.BoundaryNorm(bounds, cmap.N)

    plt.pcolor(data, cmap=cmap)
    plt.colorbar()
    plt.show()

    它给我的是什么:

    example_heatmap

    再说一次:我希望将热图的红色部分更改为渐变色(理想情况下,颜色栏不应该具有与现在相同大小的所有颜色)。

    谢谢。

    更新:

    我终于意识到,可以通过cdict定义一个颜色图,如下所示:使用matplotlib创建自己的颜色图并绘制色标。

    但是,我根本达不到我的期望。

    我有这个cdict

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    cdict = {'red':   ((0.0,  1.0, 1.0),
                       (0.0001,  1.0, 1.0),
                       (lower_bound, 0.99, 0.99),
                       (threshold, 0.99, 0.99),
                       (threshold + 0.0001, 0.98, 0.98),
                       (upper_bound,  0.57, 0.57),
                       (upper_bound + 0.0001,  0.0, 0.0),
                       (1.0, 0.0, 0.0)),

             'green': ((0.0,  1.0, 1.0),
                       (0.0001, 1.0, 1.0),
                       (lower_bound, 0.92, 0.92),
                       (threshold, 0.92, 0.92),
                       (threshold + 0.0001, 0.63, 0.63),
                       (upper_bound,  0.0, 0.0),
                       (upper_bound + 0.0001,  0.0, 0.0),
                       (1.0, 0.0, 0.0)),

             'blue':  ((0.0,  1.0, 1.0),
                       (0.0001,  1.0, 1.0),
                       (lower_bound, 0.82, 0.82),
                       (threshold, 0.82, 0.82),
                       (threshold + 0.0001, 0.42, 0.42),
                       (upper_bound, 0.0, 0.0),
                       (upper_bound + 0.0001,  0.0, 0.0),
                       (1.0, 0.0, 0.0))
            }
    cmap = LinearSegmentedColormap('cdict', cdict)

    界线:

    1
    2
    3
    lower_bound = data[data != 0].min()
    upped_bound = data.max()
    threshold = 0.2

    对我来说(lower_bound, upper_bound, threshold) = (0.02249988938707692, 0.6575927961263812, 0.2)

    情节:

    1
    2
    3
    fig, ax = plt.subplots(figsize = (15, 6))
    im = ax.imshow(data, cmap = cmap)
    cbar = ax.figure.colorbar(im, ax = ax)

    但是,我得到这个:

    second_try

    这怎么可能?如果根据我对cdict的理解,仅将黑色分配给upper_bound以上的值,为什么为什么会有这么多的黑色正方形,这却没有意义,因为upper_bound是所有数组的最大值...


    您希望白色从0到阈值,并且从阈值到1呈梯度。当数据也在0到1之间时,这非常容易。 值小于0的颜色可以通过.set_under设置。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.colors import LinearSegmentedColormap


    data = np.random.rand(10,10) * 2 - 1.3

    thresh = 0.2
    nodes = [0,thresh, thresh, 1.0]
    colors = ["white","white","red","indigo"]
    cmap = LinearSegmentedColormap.from_list("", list(zip(nodes, colors)))
    cmap.set_under("gray")

    fig, ax = plt.subplots()
    im = ax.imshow(data, cmap=cmap, vmin=0, vmax=1)
    fig.colorbar(im, extend="min")
    plt.show()

    enter image description here