简体   繁体   English

matplotlib中的离散然后线性色图

[英]Discrete then linear colormap in matplotlib

I have a matrix of data ranging from 0 to 102, and when using imshow i'd like to have 0 displayed as burnt red, 1 displayed as yellow-green and every other value from 2 to 102 in a linear gradient from standard green to dark green. 我的数据矩阵范围为0到102,使用imshow时,我希望将0显示为深红色,将1显示为黄绿色,其他所有值从2到102呈线性梯度变化,从标准绿色到绿色。深绿色。

So far I've tried using the colormap 'Greens' and replacing the first two values but I has inconsistent results and I don't know how to use only half of the colormap. 到目前为止,我已经尝试使用颜色表“ Greens”并替换前两个值,但是结果不一致,而且我不知道如何仅使用颜色表的一半。 I've also tried to generate my own colormap using a colordict and then overriding the first two entries but it also has inconsitent results depending on the data submitted (for example 1 displaying as burnt red) 我也尝试过使用colordict生成自己的颜色图,然后覆盖前两个条目,但是根据提交的数据,结果也不一致(例如1显示为红色)

You could use make_colormap to make a custom colormap: 您可以使用make_colormap制作自定义颜色图:

mygreen = make_colormap([c('burnt red'), 
                         c('yellow green'), idx[1], c('yellow green'), 
                         (0,1,0), idx[2], (0,1,0),  # RGB (0,1,0) is standard green?
                         c('dark green')])
  • The argument to make_colormap is a sequence of RGB values and floats. make_colormap的参数是RGB值和浮点数的序列。

  • Every float is sandwiched between two RGB values. 每个浮点都夹在两个RGB值之间。

  • The floats indicate locations (on a scale from 0.0 to 1.0) where the color map transitions from one RGB color to the next. 浮点数指示颜色图从一种RGB颜色过渡到另一种颜色的位置(范围从0.0到1.0)。

  • The first and last values in the sequence are the first and last colors in the color map. 序列中的第一个和最后一个值是颜色图中的第一个和最后一个颜色。


import numpy as np
import matplotlib.colors as mcolors
import matplotlib.pyplot as plt
np.random.seed(2016)

def make_colormap(seq):
    """Return a LinearSegmentedColormap
    seq: a sequence of floats and RGB-tuples. 
      - Every float is sandwiched between two RGB values.
      - The floats indicate locations (on a scale from 0.0 to 1.0) where the
        color map transitions from one RGB color to the next.
      - The floats should be in increasing order
      - The first and last values in the sequence are the first and last
        colors in the color map.
    https://stackoverflow.com/q/16834861/190597 (unutbu)
    """
    seq = [(None,) * 3, 0.0] + list(seq) + [1.0, (None,) * 3]
    cdict = {'red': [], 'green': [], 'blue': []}
    for i, item in enumerate(seq):
        if isinstance(item, float):
            r1, g1, b1 = seq[i - 1]
            r2, g2, b2 = seq[i + 1]
            cdict['red'].append([item, r1, r2])
            cdict['green'].append([item, g1, g2])
            cdict['blue'].append([item, b1, b2])
    return mcolors.LinearSegmentedColormap('CustomMap', cdict)

# There are 103 integers from 0 to 102 (inclusive)
idx = np.linspace(0, 1, 103)
c = mcolors.ColorConverter().to_rgb
mygreen = make_colormap([c('burnt red'), 
                         c('yellow green'), idx[1], c('yellow green'), 
                         (0,1,0), idx[2], (0,1,0),  # RGB (0,1,0) is standard green?
                         c('dark green')])

arr = np.random.randint(0, 103, size=(11, 11))
print(np.where(arr==0))
print(np.where(arr==1))
plt.imshow(arr, interpolation='nearest', cmap=mygreen, vmin=0, vmax=102)
plt.colorbar(ticks=list(range(0, 100, 10))+[102])
plt.show()

在此处输入图片说明

Another (probably better) option is to modify arr to take advantage of matplotlib's cmap.set_under and cmap.set_over methods. 另一个(可能更好)的选项是修改arr以利用matplotlib的cmap.set_undercmap.set_over方法。 These colormap methods allow you to set a color for all values that go under or over specified limits: 这些颜色图方法使您可以为所有低于或超过指定限制的值设置颜色:

cmap = make_colormap([(0,1,0), c('dark green')])
cmap.set_under('burnt red')
cmap.set_over('yellow green')

Thus, in the special case where you have just two special colors, you could modify arr so 0 gets mapped to, say, a negative number, and 1 gets mapped to a number larger than 100, and shift the rest of the numbers to range from 0 to 100: 因此,在特殊情况下,如果您只有两种特殊颜色,则可以修改arr以便将0映射为负数,将1映射为大于100的数字,然后将其余数字移动到range从0到100:

arr -= 2   
arr = np.where(arr==-1, 102, arr)

For example, 例如,

import numpy as np
import matplotlib.colors as mcolors
import matplotlib.pyplot as plt
np.random.seed(2016)

def make_colormap(seq):
    """Return a LinearSegmentedColormap
    seq: a sequence of floats and RGB-tuples. 
      - Every float is sandwiched between two RGB values.
      - The floats indicate locations (on a scale from 0.0 to 1.0) where the
        color map transitions from one RGB color to the next.
      - The floats should be in increasing order
      - The first and last values in the sequence are the first and last
        colors in color map.
    https://stackoverflow.com/q/16834861/190597 (unutbu)
    """
    seq = [(None,) * 3, 0.0] + list(seq) + [1.0, (None,) * 3]
    cdict = {'red': [], 'green': [], 'blue': []}
    for i, item in enumerate(seq):
        if isinstance(item, float):
            r1, g1, b1 = seq[i - 1]
            r2, g2, b2 = seq[i + 1]
            cdict['red'].append([item, r1, r2])
            cdict['green'].append([item, g1, g2])
            cdict['blue'].append([item, b1, b2])
    return mcolors.LinearSegmentedColormap('CustomMap', cdict)

c = mcolors.ColorConverter().to_rgb
cmap = make_colormap([(0,1,0), c('dark green')])
cmap.set_under('burnt red')
cmap.set_over('yellow green')

arr = np.random.randint(0, 102, size=(11, 11))
# modify arr so that 0 is mapped to a negative number (-2) and 1 is mapped to a
# positive number greater than 100, (say, 102), and all other values are
# decreased by 2
arr -= 2   
arr = np.where(arr==-1, 102, arr)

plt.imshow(arr, interpolation='nearest', cmap=cmap, vmin=0, vmax=100)
plt.colorbar(extend='both')
plt.show()

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM