Python 使用matplotlib和打印颜色比例创建自己的颜色贴图

Python 使用matplotlib和打印颜色比例创建自己的颜色贴图,python,matplotlib,plot,Python,Matplotlib,Plot,我有以下问题,我想创建我自己的颜色映射(红色混合紫色混合蓝色),映射到-2和+2之间的值,并想使用它为我的绘图中的点着色。 然后,绘图的色标应位于右侧。 到目前为止,我就是这样创建地图的。但我不确定它是否混合了颜色 cmap = matplotlib.colors.ListedColormap(["red","violet","blue"], name='from_list', N=None) m = cm.ScalarMappable(norm=norm, cmap=cmap) 这样我可以

我有以下问题,我想创建我自己的颜色映射(红色混合紫色混合蓝色),映射到-2和+2之间的值,并想使用它为我的绘图中的点着色。 然后,绘图的色标应位于右侧。

到目前为止,我就是这样创建地图的。但我不确定它是否混合了颜色

cmap = matplotlib.colors.ListedColormap(["red","violet","blue"], name='from_list', N=None)
m = cm.ScalarMappable(norm=norm, cmap=cmap)

这样我可以将颜色映射到值。

colors = itertools.cycle([m.to_rgba(1.22), ..])

然后我绘制它:

for i in range(0, len(array_dg)):
  plt.plot(array_dg[i], markers.next(),alpha=alpha[i], c=colors.next())

我的问题是:
1.我无法绘制颜色比例。

2.我不能完全确定我的比例是否创建了连续(平滑)的色阶。

这里有一个示例。 文档字符串对于理解
cdict
。一旦你把它放在腰带下面,你就可以使用如下的
cdict

cdict = {'red':   ((0.0, 1.0, 1.0), 
                   (0.1, 1.0, 1.0),  # red 
                   (0.4, 1.0, 1.0),  # violet
                   (1.0, 0.0, 0.0)), # blue

         'green': ((0.0, 0.0, 0.0),
                   (1.0, 0.0, 0.0)),

         'blue':  ((0.0, 0.0, 0.0),
                   (0.1, 0.0, 0.0),  # red
                   (0.4, 1.0, 1.0),  # violet
                   (1.0, 1.0, 0.0))  # blue
          }
虽然
cdict
格式给了您很大的灵活性,但我发现它非常简单 渐变它的格式很不直观。下面是一个实用函数来帮助您 生成简单的LinearSegmentedColormaps:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors


def make_colormap(seq):
    """Return a LinearSegmentedColormap
    seq: a sequence of floats and RGB-tuples. The floats should be increasing
    and in the interval (0,1).
    """
    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
rvb = make_colormap(
    [c('red'), c('violet'), 0.33, c('violet'), c('blue'), 0.66, c('blue')])
N = 1000
array_dg = np.random.uniform(0, 10, size=(N, 2))
colors = np.random.uniform(-2, 2, size=(N,))
plt.scatter(array_dg[:, 0], array_dg[:, 1], c=colors, cmap=rvb)
plt.colorbar()
plt.show()


顺便说一下,
for循环

for i in range(0, len(array_dg)):
  plt.plot(array_dg[i], markers.next(),alpha=alpha[i], c=colors.next())

为每次调用
plt绘制一个点。绘制
。这将适用于少量点,但在许多点上会变得非常缓慢
plt.plot
只能绘制一种颜色,但是
plt.scatter
可以为每个点指定不同的颜色。因此,
plt.scatter
是一个不错的选择。

如果您想自动创建一个常用的自定义发散颜色贴图,这个模块结合@unutbu方法对我来说效果很好

def diverge_map(high=(0.565, 0.392, 0.173), low=(0.094, 0.310, 0.635)):
    '''
    low and high are colors that will be used for the two
    ends of the spectrum. they can be either color strings
    or rgb color tuples
    '''
    c = mcolors.ColorConverter().to_rgb
    if isinstance(low, basestring): low = c(low)
    if isinstance(high, basestring): high = c(high)
    return make_colormap([low, c('white'), 0.5, c('white'), high])
高值和低值可以是字符串颜色名称或rgb元组。这是使用以下公式得出的结果:

由于其他答案中使用的方法对于如此简单的任务来说似乎相当复杂,下面是一个新的答案:

您可以使用
LinearSegmentedColormap
,而不是生成离散颜色映射的
ListedColormap
。可以使用
from\u list
方法从列表中轻松创建此项

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

x,y,c = zip(*np.random.rand(30,3)*4-2)

norm=plt.Normalize(-2,2)
cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", ["red","violet","blue"])

plt.scatter(x,y,c=c, cmap=cmap, norm=norm)
plt.colorbar()
plt.show()


更一般地说,如果您有一个值列表(例如
[-2.,-1,2]
)和相应的颜色(例如
[“红色”、“紫色”、“蓝色”]
),例如
n
第th个值应该对应于
n
第th个颜色,那么您可以规范化这些值,并将它们作为元组从\u list
方法提供给

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

x,y,c = zip(*np.random.rand(30,3)*4-2)

cvals  = [-2., -1, 2]
colors = ["red","violet","blue"]

norm=plt.Normalize(min(cvals),max(cvals))
tuples = list(zip(map(norm,cvals), colors))
cmap = matplotlib.colors.LinearSegmentedColormap.from_list("", tuples)

plt.scatter(x,y,c=c, cmap=cmap, norm=norm)
plt.colorbar()
plt.show()

这似乎对我有用

def make_Ramp( ramp_colors ): 
    from colour import Color
    from matplotlib.colors import LinearSegmentedColormap

    color_ramp = LinearSegmentedColormap.from_list( 'my_list', [ Color( c1 ).rgb for c1 in ramp_colors ] )
    plt.figure( figsize = (15,3))
    plt.imshow( [list(np.arange(0, len( ramp_colors ) , 0.1)) ] , interpolation='nearest', origin='lower', cmap= color_ramp )
    plt.xticks([])
    plt.yticks([])
    return color_ramp

custom_ramp = make_Ramp( ['#754a28','#893584','#68ad45','#0080a5' ] ) 

你能澄清一下你的问题吗?例如,在谈论点时,
c=
指定线的颜色。您只能指定一个
markerfacecolor
,如果您确实想要点,分散可能是更好的选择。实际上,
ListedColormap
是列出的,不是连续的,请参见
LinearSegmentedColormap
。这很奇怪,它应该是点,看起来像点。你可以偏离路线,但这是你应该澄清的。我们看不到您使用的打印样式。如果您使用
plt.plot(values,'o')
,您将只打印标记,而不打印线条,但是标记将有一个固定的颜色,该颜色不会(且不能)随值变化。现在我遇到了一个问题。我还想得到一个不同的标记符号根据颜色(我有13种不同的颜色)。但是散点图只允许每个图有一个标记,或者我遗漏了什么吗?在这种情况下,您需要为每个颜色/标记组合调用一次
plt.scatter
(或
plt.plot
)。为什么我不能在plt.set_cmap()中使用这个很棒的函数创建颜色贴图?错误很长,最后一行是ValueError:Colormap CustomMap无法识别。@Ilya:首先注册Colormap:
plt。注册cmap(name=rvb.name,cmap=rvb)
,然后调用
plt.set\u cmap(rvb)
@As3adTintin:
rvb
上面是一个完整的Colormap,就像
plt.cm.cool
。因此它们是可替换的:
color=rvb(x/y)
。您现在如何将自己定义的范围传递给它,例如,
红色
对应于
-5
紫色
对应于
1
蓝色
对应于
100
?如果您能看看我提出的问题,我将不胜感激。使用相应绘图方法的
vmin
vmax
norm
参数。这可能不如接受答案中的完整自定义地图灵活,但这非常复杂,我想这正是大多数人想要定制彩色地图时需要的答案。@Notso
LinearSegmentedColormap.from_list(“,[(0,“红色”),(.1,“紫色”),(.5,“蓝色”),(1.0,“绿色”)
。我更新了答案,希望能让这更清楚。@ShaunLowis在这种情况下,您可以自己插入RGB值。更一般地说,您可以先创建颜色贴图,然后以非等距的步骤获取贴图的颜色。例如,如果
cmap
是原始颜色映射,则
cvals=[-12,-2,0,2,12];colors=cmap(plt.Normalize(-12,12)(np.array(cvals))
将为压缩贴图提供新的颜色。