在Matplotlib中设置与特定数据范围对应的离散色图

时间:2016-11-15 04:22:55

标签: python matplotlib

一些背景

我有一个形状为(50,50)的二维数组,数据值范围为-40~40。 但我想在三个数据范围内绘制数据[< 0],[0,20],[> 20]

然后,我需要生成一个对应于三个部分的色彩映射表。

我现在有些想法

## ratio is the original 2-d array
binlabel = np.zeros_like(ratio)
binlabel[ratio<0] = 1
binlabel[(ratio>0)&(ratio<20)] = 2
binlabel[ratio>20] = 3

def discrete_cmap(N, base_cmap=None):
    base = plt.cm.get_cmap(base_cmap)
    color_list = base(np.linspace(0, 1, N))
    cmap_name = base.name + str(N)
    return base.from_list(cmap_name, color_list, N)

fig  = plt.figure()
ax = plt.gca()
plt.pcolormesh(binlabel, cmap = discrete_cmap(3, 'jet'))
divider = make_axes_locatable(ax)
cax = divider.append_axes("bottom", size="4%", pad=0.45)
cbar = plt.colorbar(ratio_plot, cax=cax, orientation="horizontal")
labels = [1.35,2,2.65]
loc    = labels
cbar.set_ticks(loc)
cbar.ax.set_xticklabels(['< 0', '0~20', '>20']) 

有没有更好的方法?任何建议都会很感激。

1 个答案:

答案 0 :(得分:2)

使用ListedColormapBoundaryNorm对其他问题有各种答案,但这里有另一种选择。我忽略了您的颜色栏的位置,因为它与您的问题无关。

您可以通过调用binlabel替换np.digitize()计算,并使用discrete_cmap()参数替换lut函数get_cmap()。此外,我发现将颜色边界放在索引之间的.5中点更容易,而不是缩放到奇数的笨拙部分:

import matplotlib.colors as mcol
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import numpy as np

ratio = np.random.random((50,50)) * 50.0 - 20.0

fig2, ax2 = plt.subplots(figsize=(5,5))

# Turn the data into an array of N bin indexes (i.e., 0, 1 and 2).
bounds = [0,20]
iratio = np.digitize(ratio.flat,bounds).reshape(ratio.shape)

# Create a colormap containing N colors and a Normalizer that defines where 
# the boundaries of the colors should be relative to the indexes (i.e., -0.5, 
# 0.5, 1.5, 2.5).
cmap = cm.get_cmap("jet",lut=len(bounds)+1)
cmap_bounds = np.arange(len(bounds)+2) - 0.5
norm = mcol.BoundaryNorm(cmap_bounds,cmap.N)

# Plot using the colormap and the Normalizer.
ratio_plot = plt.pcolormesh(iratio,cmap=cmap,norm=norm)
cbar = plt.colorbar(ratio_plot,ticks=[0,1,2],orientation="horizontal")
cbar.set_ticklabels(["< 0","0~20",">20"])

Example discrete color bar