2017-03-07 61 views
2

我有3组值的数组:0和1(绿色梯度) Matplotlib:如何在2个或更多的颜色中切割一个颜色条?

  • 值等于2(红色)之间

    • 值等于3(灰)

    多亏了这个帖子(Define a colormap for each set of values in an array)我能得到这个代码:

    from random import random 
    import numpy as np 
    import matplotlib.pyplot as plt 
    import matplotlib.colors as mcolors 
    from matplotlib import cm 
    
    n=11 
    tab = np.array([[random() for i in range(n)] for j in range(n)]) 
    tab[1,2] = 2. 
    tab[3,4] = 2. 
    tab[5,6] = 3. 
    tab[7,8] = 3. 
    
    values1 = np.ma.masked_array(tab, tab > 1.) 
    values2 = np.ma.masked_array(tab, tab != 2.) 
    values3 = np.ma.masked_array(tab, tab != 3.) 
    
    # 50 values for later use from 0 to 1 
    greens = cm.Greens(np.linspace(0,1, num=50)) 
    # 25 values for later use from 1 to 1.5 
    greensfill = cm.Greens(np.ones(25)) 
    # 50 values red for later use from 1.5 to 2.5 
    red = [(1,0,0,1)]*len(greens) 
    # 50 values gray for later use from 2.5 to 3.5 
    gray = [(.5,.5,.5,1)]*len(greens) 
    
    colors = np.vstack((greens, greensfill, red, gray)) 
    # in total we now have 175 colors in the colormap 
    mycmap = mcolors.LinearSegmentedColormap.from_list('my_colormap', colors) 
    
    #we now map those 175 colors to the range between 0 and 3.5 
    im = plt.imshow(tab, cmap = mycmap, interpolation="none", vmin=0, vmax=3.5) 
    cb = plt.colorbar(im) 
    cb.set_ticks([0,1,2,3]) 
    
    plt.show() 
    

    下面是结果:

    enter image description here

    我的问题是:可以matplotlib获得通过削减现有的颜色映射成3个独立的颜色表或者相近的东西像下面的图片(编辑用Photoshop做)?

    enter image description here

    编辑:

    greens = cm.Greens(np.linspace(0,1, num=75)) 
    red = [(1,0,0,1)]*(len(greens)/2) 
    white = [(1,1,1,1)]*3 
    black = [(0,0,0,1)]*1 
    gray = [(.5,.5,.5,1)]*(len(greens)/2) 
    
    colors = np.vstack((greens, black, white, black, red, black, white, black, gray)) 
    mycmap = mcolors.LinearSegmentedColormap.from_list('my_colormap', colors) 
    

    我修改了代码,并获得内容,但它并不好看和索引是在错误的地方:

    enter image description here

  • +0

    伟大的想法(因为我没有在互联网上看到任何类似的东西,所以我觉得它会有点困难)!我该如何移动我想要的索引? –

    +0

    @LoïcPoncin您可以通过'set_ticks'指定勾号位置并通过'set_ticklabels'勾选标签。所以你可以通过'cb.set_ticks([0,1.5,2,3])来获得右手绘图的刻度+标签; cb.set_ticklabels(['0','1','2','3'])'。然而,它将标签'1'设置在位置1.5,因此实际上使颜色条无效。同样在你的右手绘图中(红色区域),红色区域从1到2.5,灰色区域从2.5到3.5,但是它们的大小相同。绿色跨越一个类似的区域,如灰色和小于红色的区域,但是它们是三者中最大的一个。 –

    +0

    谢谢。 @a_guest是的,我知道它并不真正对应于彩条的原理。事实上,我在一个关于森林火灾的学校项目中工作,在我的动画中,绿色渐变(0和1之间)对应于像素中包含的植被的能力,红色像素对应于燃烧的树木,灰色对应于已经燃烧并在灰烬中的树木。所以红色和灰色的颜色就是传说中的动画。 –

    回答

    3

    首先:不要更改颜色表!这是用于指定数据的映射,因此如果更改它,数据表示形式与您最初的目标不同。

    你可以做的是创建3个不同的颜色条,如下所示。注意区别:我们有一个单一的色彩映射,但有三个色彩条,它们都显示了一个色彩映射的一部分。

    enter image description here

    from random import random 
    import numpy as np 
    import matplotlib.pyplot as plt 
    import matplotlib.colors as mcolors 
    from matplotlib import cm 
    
    n=11 
    tab = np.array([[random() for i in range(n)] for j in range(n)]) 
    tab[1,2] = 2. 
    tab[3,4] = 2. 
    tab[5,6] = 3. 
    tab[7,8] = 3. 
    
    values1 = np.ma.masked_array(tab, tab > 1.) 
    values2 = np.ma.masked_array(tab, tab != 2.) 
    values3 = np.ma.masked_array(tab, tab != 3.) 
    
    # 50 values for later use from 0 to 1 
    greens = cm.Greens(np.linspace(0,1, num=50)) 
    # 25 values for later use from 1 to 1.5 
    greensfill = cm.Greens(np.ones(25)) 
    # 50 values red for later use from 1.5 to 2.5 
    red = [(1,0,0,1)]*len(greens) 
    # 50 values gray for later use from 2.5 to 3.5 
    gray = [(.5,.5,.5,1)]*len(greens) 
    
    colors = np.vstack((greens, greensfill, red, gray)) 
    # in total we now have 175 colors in the colormap 
    mycmap = mcolors.LinearSegmentedColormap.from_list('my_colormap', colors) 
    
    #we now map those 175 colors to the range between 0 and 3.5 
    im = plt.imshow(tab, cmap = mycmap, interpolation="none", vmin=0, vmax=3.5) 
    
    plt.subplots_adjust(top=0.90, bottom=0.1) 
    cb1ax = plt.gcf().add_axes([0.85, 0.8, 0.035, 0.1]) 
    cb2ax = plt.gcf().add_axes([0.85, 0.67, 0.035, 0.1]) 
    cb3ax = plt.gcf().add_axes([0.85, 0.1, 0.035, 0.54]) 
    
    plt.gcf().colorbar(im, cax=cb1ax, boundaries=[2.5,3.5], ticks=[3]) 
    plt.gcf().colorbar(im, cax=cb2ax, boundaries=[1.5,2.5], ticks=[2]) 
    plt.gcf().colorbar(im, cax=cb3ax, boundaries=np.linspace(0,1, num=100), ticks=[0,1]) 
    
    plt.show() 
    


    编辑:现在,它可能发生在彩条不坐间隔紧密的图像,甚至重叠的。也可能发生这样的情况,三个条的高度大于图像的高度。为了防止这种情况发生,我们可以调整栏杆大小并调整它们的位置,使它们始终看起来不错。因此脚本的下半部分可能会被下面的代码替代。

    plt.subplots_adjust(top=0.90, bottom=0.1) 
    plt.gcf().canvas.draw() 
    ax = plt.gca() 
    
    plt.subplots_adjust(top=0.90, bottom=0.1) 
    cb1ax = plt.gcf().add_axes([0.85, 0.8, 0.035, 0.1]) 
    cb2ax = plt.gcf().add_axes([0.85, 0.67, 0.035, 0.1]) 
    cb3ax = plt.gcf().add_axes([0.85, 0.1, 0.035, 0.54]) 
    
    plt.gcf().colorbar(im, cax=cb1ax, boundaries=[2.5,3.5], ticks=[3]) 
    plt.gcf().colorbar(im, cax=cb2ax, boundaries=[1.5,2.5], ticks=[2]) 
    plt.gcf().colorbar(im, cax=cb3ax, boundaries=np.linspace(0,1, num=100), ticks=[0,1]) 
    
    def resize(event=None): 
        s = 0.03 
        pos = ax.get_position() 
        smh = pos.height/8.; loh = pos.height*0.675 
        w = 0.06*pos.width; 
        x0 = pos.x1+0.065*pos.width 
        cb1ax.set_position([x0, pos.y0+loh+smh+2*s, w, smh]) 
        cb2ax.set_position([x0, pos.y0+loh+s,  w, smh]) 
        cb3ax.set_position([x0, pos.y0,    w, loh]) 
    
    resize() 
    plt.connect("resize_event", resize) 
    
    plt.show() 
    
    +0

    非常感谢!看看我得到:https://i.stack.imgur.com/PQAvH.png。如何正确地将3个颜色条对齐到我的身材右侧并且尺寸相同?我知道对于单个颜色条,它必须是'divider = make_axes_locatable(axes)',然后'cax = divider.append_axes(“right”,size =“5%”,pad = 0.2)''。以及如何将这些小特性放在数字之外,而不是内部? –

    +0

    你想要完整的数字向外指出蜱吗?然后在脚本顶部的'plt.rcParams [“xtick.direction”] =“out”'会有所帮助。分隔线不适用于3个颜色条。 “具有相同尺寸”是什么意思?他们都应该是图像高度的三分之一? – ImportanceOfBeingErnest

    +0

    我的意思是我想让这套着色器的顶部和底部与阵列的顶部和底部对齐。例如,在你的帖子中,颜色条与数组的顶部和底部正确对齐,但在我发给你的链接中却不是。感谢蜱,这正是我想要的。 –

    相关问题