102

如何生成随机颜色以传递给绘图函数的简单示例是什么?

我在循环内调用 scatter 并希望每个绘图都具有不同的颜色。

for X,Y in data:
   scatter(X, Y, c=??)

c:一种颜色。c 可以是单个颜色格式字符串,或长度为 N 的颜色规范序列,或使用 cmap 和通过 kwargs 指定的规范映射到颜色的 N 数字序列(见下文)。请注意,c 不应是单个数字 RGB 或 RGBA 序列,因为它与要进行颜色映射的值数组无法区分。c 可以是一个二维数组,其中行是 RGB 或 RGBA。

4

12 回答 12

162

我在循环内调用 scatter 并希望每个图都具有不同的颜色。

基于此,并根据您的回答:在我看来,您实际上希望数据集n 具有不同的颜色;您想将整数索引映射0, 1, ..., n-1到不同的 RGB 颜色。就像是:

将索引映射到颜色

这是执行此操作的功能:

import matplotlib.pyplot as plt

def get_cmap(n, name='hsv'):
    '''Returns a function that maps each index in 0, 1, ..., n-1 to a distinct 
    RGB color; the keyword argument name must be a standard mpl colormap name.'''
    return plt.cm.get_cmap(name, n)

问题中伪代码片段中的用法:

cmap = get_cmap(len(data))
for i, (X, Y) in enumerate(data):
   scatter(X, Y, c=cmap(i))

我使用以下代码在我的答案中生成了该图:

import matplotlib.pyplot as plt

def get_cmap(n, name='hsv'):
    '''Returns a function that maps each index in 0, 1, ..., n-1 to a distinct 
    RGB color; the keyword argument name must be a standard mpl colormap name.'''
    return plt.cm.get_cmap(name, n)

def main():
    N = 30
    fig=plt.figure()
    ax=fig.add_subplot(111)   
    plt.axis('scaled')
    ax.set_xlim([ 0, N])
    ax.set_ylim([-0.5, 0.5])
    cmap = get_cmap(N)
    for i in range(N):
        rect = plt.Rectangle((i, -0.5), 1, 1, facecolor=cmap(i))
        ax.add_artist(rect)
    ax.set_yticks([])
    plt.show()

if __name__=='__main__':
    main()

使用 Python 2.7 和 matplotlib 1.5 以及 Python 3.5 和 matplotlib 2.0 进行了测试。它按预期工作。

于 2014-09-02T16:45:29.730 回答
86
for X,Y in data:
   scatter(X, Y, c=numpy.random.rand(3,))
于 2013-02-06T02:07:50.823 回答
39

详细说明@john-mee 的答案,如果您有任意长的数据但不需要严格唯一的颜色:

对于蟒蛇 2:

from itertools import cycle
cycol = cycle('bgrcmk')

for X,Y in data:
    scatter(X, Y, c=cycol.next())

对于蟒蛇 3:

from itertools import cycle
cycol = cycle('bgrcmk')

for X,Y in data:
    scatter(X, Y, c=next(cycol))

这样做的好处是颜色易于控制并且很短。

于 2015-01-29T19:25:00.600 回答
36

有一段时间,我对 matplotlib 不生成具有随机颜色的颜色图这一事实感到非常恼火,因为这是分割和聚类任务的常见需求。

通过仅生成随机颜色,我们可能会以一些太亮或太暗结束,从而使可视化变得困难。此外,通常我们需要第一个或最后一个颜色为黑色,代表背景或异常值。所以我为我的日常工作写了一个小函数

这是它的行为:

new_cmap = rand_cmap(100, type='bright', first_color_black=True, last_color_black=False, verbose=True)

生成的颜色图

比您只使用new_cmap作为 matplotlib 上的颜色图:

ax.scatter(X,Y, c=label, cmap=new_cmap, vmin=0, vmax=num_labels)

代码在这里:

def rand_cmap(nlabels, type='bright', first_color_black=True, last_color_black=False, verbose=True):
    """
    Creates a random colormap to be used together with matplotlib. Useful for segmentation tasks
    :param nlabels: Number of labels (size of colormap)
    :param type: 'bright' for strong colors, 'soft' for pastel colors
    :param first_color_black: Option to use first color as black, True or False
    :param last_color_black: Option to use last color as black, True or False
    :param verbose: Prints the number of labels and shows the colormap. True or False
    :return: colormap for matplotlib
    """
    from matplotlib.colors import LinearSegmentedColormap
    import colorsys
    import numpy as np


    if type not in ('bright', 'soft'):
        print ('Please choose "bright" or "soft" for type')
        return

    if verbose:
        print('Number of labels: ' + str(nlabels))

    # Generate color map for bright colors, based on hsv
    if type == 'bright':
        randHSVcolors = [(np.random.uniform(low=0.0, high=1),
                          np.random.uniform(low=0.2, high=1),
                          np.random.uniform(low=0.9, high=1)) for i in xrange(nlabels)]

        # Convert HSV list to RGB
        randRGBcolors = []
        for HSVcolor in randHSVcolors:
            randRGBcolors.append(colorsys.hsv_to_rgb(HSVcolor[0], HSVcolor[1], HSVcolor[2]))

        if first_color_black:
            randRGBcolors[0] = [0, 0, 0]

        if last_color_black:
            randRGBcolors[-1] = [0, 0, 0]

        random_colormap = LinearSegmentedColormap.from_list('new_map', randRGBcolors, N=nlabels)

    # Generate soft pastel colors, by limiting the RGB spectrum
    if type == 'soft':
        low = 0.6
        high = 0.95
        randRGBcolors = [(np.random.uniform(low=low, high=high),
                          np.random.uniform(low=low, high=high),
                          np.random.uniform(low=low, high=high)) for i in xrange(nlabels)]

        if first_color_black:
            randRGBcolors[0] = [0, 0, 0]

        if last_color_black:
            randRGBcolors[-1] = [0, 0, 0]
        random_colormap = LinearSegmentedColormap.from_list('new_map', randRGBcolors, N=nlabels)

    # Display colorbar
    if verbose:
        from matplotlib import colors, colorbar
        from matplotlib import pyplot as plt
        fig, ax = plt.subplots(1, 1, figsize=(15, 0.5))

        bounds = np.linspace(0, nlabels, nlabels + 1)
        norm = colors.BoundaryNorm(bounds, nlabels)

        cb = colorbar.ColorbarBase(ax, cmap=random_colormap, norm=norm, spacing='proportional', ticks=None,
                                   boundaries=bounds, format='%1i', orientation=u'horizontal')

    return random_colormap

它也在 github 上: https ://github.com/delestro/rand_cmap

于 2015-09-11T09:36:45.713 回答
19

当少于 9 个数据集时:

colors = "bgrcmykw"
color_index = 0

for X,Y in data:
    scatter(X,Y, c=colors[color_index])
    color_index += 1
于 2013-02-06T02:20:37.000 回答
16

由于问题是How to generate random colors in matplotlib?并且当我正在寻找有关 的答案pie plots时,我认为值得在这里(对于pies)提出答案

import numpy as np
from random import sample
import matplotlib.pyplot as plt
import matplotlib.colors as pltc
all_colors = [k for k,v in pltc.cnames.items()]

fracs = np.array([600, 179, 154, 139, 126, 1185])
labels = ["label1", "label2", "label3", "label4", "label5", "label6"]
explode = ((fracs == max(fracs)).astype(int) / 20).tolist()

for val in range(2):
    colors = sample(all_colors, len(fracs))
    plt.figure(figsize=(8,8))
    plt.pie(fracs, labels=labels, autopct='%1.1f%%', 
            shadow=True, explode=explode, colors=colors)
    plt.legend(labels, loc=(1.05, 0.7), shadow=True)
    plt.show()

输出

在此处输入图像描述

在此处输入图像描述

于 2018-07-24T14:20:20.293 回答
10

这是阿里答案的更简洁版本,每个情节给出一种不同的颜色:

import matplotlib.pyplot as plt

N = len(data)
cmap = plt.cm.get_cmap("hsv", N+1)
for i in range(N):
    X,Y = data[i]
    plt.scatter(X, Y, c=cmap(i))
于 2017-02-07T01:48:43.417 回答
5

根据 Ali 和 Champitoad 的回答:

如果你想尝试不同的调色板,你可以在几行中做到这一点:

cmap=plt.cm.get_cmap(plt.cm.viridis, 143)

143是您要采样的颜色数

我选择 143 是因为颜色图上的整个颜色范围都在这里发挥作用。您可以做的是每次迭代都对第 n 个颜色进行采样以获得颜色图效果。

n=20
for i,(x,y) in enumerate(points):
    plt.scatter(x, y, c=cmap(n*i))
于 2017-12-22T22:01:48.233 回答
2

改进答案https://stackoverflow.com/a/14720445/6654512以使用 Python3。那段代码有时会生成大于 1 的数字,matplotlib 会抛出错误。

for X,Y in data:
   scatter(X, Y, c=numpy.random.random(3))
于 2017-07-03T12:13:38.943 回答
1
enter code here

import numpy as np

clrs = np.linspace( 0, 1, 18 )  # It will generate 
# color only for 18 for more change the number
np.random.shuffle(clrs)
colors = []
for i in range(0, 72, 4):
    idx = np.arange( 0, 18, 1 )
    np.random.shuffle(idx)
    r = clrs[idx[0]]
    g = clrs[idx[1]]
    b = clrs[idx[2]]
    a = clrs[idx[3]]
    colors.append([r, g, b, a])
于 2019-07-16T11:35:15.857 回答
1

如果您想确保颜色不同 - 但不知道需要多少种颜色。尝试这样的事情。它从光谱的相对两侧选择颜色并系统地增加粒度。

import math

def calc(val, max = 16):
    if val < 1:
        return 0
    if val == 1:
        return max

    l = math.floor(math.log2(val-1))    #level 
    d = max/2**(l+1)                    #devision
    n = val-2**l                        #node
    return d*(2*n-1)
import matplotlib.pyplot as plt

N = 16
cmap = cmap = plt.cm.get_cmap('gist_rainbow', N)

fig, axs = plt.subplots(2)
for ax in axs:
    ax.set_xlim([ 0, N])
    ax.set_ylim([-0.5, 0.5])
    ax.set_yticks([])

for i in range(0,N+1):
    v = int(calc(i, max = N))
    rect0 = plt.Rectangle((i, -0.5), 1, 1, facecolor=cmap(i))
    rect1 = plt.Rectangle((i, -0.5), 1, 1, facecolor=cmap(v))
    axs[0].add_artist(rect0)
    axs[1].add_artist(rect1)

plt.xticks(range(0, N), [int(calc(i, N)) for i in range(0, N)])
plt.show()

输出

感谢 @Ali 提供基本实现。

于 2019-11-07T10:29:09.077 回答
1

可重复的结果

# generate random colors
colors_ = lambda n: list(map(lambda i: "#" + "%06x" % random.randint(0, 0xFFFFFF),range(n)))

fig = plt.figure()
fig.subplots_adjust(hspace=0.4, wspace=0.4)

# how many random colors to generate?
colors = colors_(6)
for i,color in zip(range(1, 7), colors):
    ax = fig.add_subplot(2, 3, i)
    ax.text(0.5, 0.5, str((2, 3, i)),
           fontsize=18, ha='center', color=color)

输出

于 2021-07-20T18:38:01.143 回答