【问题标题】:Matplotlib: combine gradient colormap with listed colormapMatplotlib:将渐变颜色图与列出的颜色图相结合
【发布时间】:2019-12-20 22:59:22
【问题描述】:

我有一个 DataFrame,其值来自 (0, 1)(请注意,这两个数字都不包括在内)。

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

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

  1. 如果数据缺失 (==0):热图中的白色(只有一种白色)。
  2. 如果数据低于阈值(例如 0
  3. 如果数据高于阈值:红色(或任何其他,无关紧要)颜色的渐变颜色图。

这里的关键是我希望 1. 和 2 具有精确的灰色和精确的白色。我不希望低于阈值的值和高于阈值的值之间有任何渐变。

我已经看到这个关于组合两个颜色图的问题:Combining two matplotlib colormaps,但我真的不明白该代码中的何处将负值映射到不同的颜色图,或者如何使第二个颜色图不渐变。

数据仅用于示例:

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

还有ListedColormap:

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()

它给了我什么:

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

谢谢。

更新:

我终于意识到可以使用通过cdict 定义的一个颜色图来回答这个问题:Create own colormap using matplotlib and plot color scale

但是,我完全没有达到我的预期。

我有这个cdict

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)

界限:

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

我在哪里(lower_bound, upper_bound, threshold) = (0.02249988938707692, 0.6575927961263812, 0.2)

剧情:

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

但是,我明白了:

这怎么可能?如果黑色根据我对cdict 的理解仅分配给高于upper_bound 的值,为什么我有这么多黑色方块,这没有意义,因为upper_bound 是所有数组中的最大值...

【问题讨论】:

  • @Ardweaden 根据其他问题的答案改进了一些东西,但问题仍未解决。
  • 我认为您的 cdict 设置不正确。您可以试试我在答案中发布的那个(为方便起见)?
  • @Ardweaden 我试过了,但这不是我所期望的。颜色条应如下所示:白色 0 左右,浅色至 0.2,渐变从 0.2 到末尾。你给的:0 左右的黑色,渐变到 ~1.5,之后是白色。
  • 您能否发布一张您获得数据的图片?那会很有帮助。

标签: python matplotlib


【解决方案1】:

您需要从 0 到阈值的白色,以及从阈值到 1 的渐变。当您的数据也在 0 和 1 之间的范围内时,这很容易。低于 0 的值可以通过.set_under 设置颜色。

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()

【讨论】:

    猜你喜欢
    • 2019-05-14
    • 1970-01-01
    • 1970-01-01
    • 2018-12-13
    • 1970-01-01
    • 2013-01-28
    • 2019-12-07
    • 1970-01-01
    • 2012-02-12
    相关资源
    最近更新 更多