Python 如何在 matplotlib 中生成随机颜色?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14720331/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:15:11  来源:igfitidea点击:

How to generate random colors in matplotlib?

pythonmatplotlib

提问by John Mee

What's the trivial example of how to generate random colors for passing to plotting functions?

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

I'm calling scatter inside a loop and want each plot a different color.

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

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

c: a color. c can be a single color format string, or a sequence of color specifications of length N, or a sequence of N numbers to be mapped to colors using the cmap and norm specified via kwargs (see below). Note that c should not be a single numeric RGB or RGBA sequence because that is indistinguishable from an array of values to be colormapped. c can be a 2-D array in which the rows are RGB or RGBA, however.

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

采纳答案by Charles Brunet

for X,Y in data:
   scatter(X, Y, c=numpy.random.rand(3,))

回答by John Mee

When less than 9 datasets:

当少于 9 个数据集时:

colors = "bgrcmykw"
color_index = 0

for X,Y in data:
    scatter(X,Y, c=colors[color_index])
    color_index += 1

回答by Ali

I'm calling scatter inside a loop and want each plot in a different color.

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

Based on that, and on your answer: It seems to me that you actually want ndistinctcolors for your datasets; you want to map the integer indices 0, 1, ..., n-1to distinct RGB colors.Something like:

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

mapping index to color

将索引映射到颜色

Here is the function to do it:

这是执行此操作的函数:

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)

Usage in your pseudo-code snippet in the question:

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

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


I generated the figure in my answer with the following code:

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

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()

Tested with both Python 2.7 & matplotlib 1.5, and with Python 3.5 & matplotlib 2.0. It works as expected.

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

回答by user3240588

elaborating @john-mee 's answer, if you have arbitrarily long data but don't need strictly unique colors:

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

for python 2:

对于蟒蛇 2:

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

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

for python 3:

对于蟒蛇 3:

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

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

this has the advantage that the colors are easy to control and that it's short.

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

回答by Delestro

For some time I was really annoyed by the fact that matplotlib doesn't generate colormaps with random colors, as this is a common need for segmentation and clustering tasks.

有一段时间我真的很恼火,因为 matplotlib 不会生成带有随机颜色的颜色图,因为这是分割和聚类任务的常见需求。

By just generating random colors we may end with some that are too bright or too dark, making visualization difficult. Also, usually we need the first or last color to be black, representing the background or outliers. So I've wrote a small function for my everyday work

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

Here's the behavior of it:

这是它的行为:

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

Generated colormap

生成的颜色图

Than you just use new_cmapas your colormap on matplotlib:

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

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

The code is here:

代码在这里:

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

It's also on github: https://github.com/delestro/rand_cmap

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

回答by Champitoad

Here is a more concise version of Ali's answer giving one distinct color per plot :

这是 Ali 答案的更简洁版本,每个图给出一种不同的颜色:

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))

回答by Ale Solano

Improving the answer https://stackoverflow.com/a/14720445/6654512to work with Python3. That piece of code would sometimes generate numbers greater than 1 and matplotlib would throw an error.

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

for X,Y in data:
   scatter(X, Y, c=numpy.random.random(3))

回答by ai-shwarya

Based on Ali's and Champitoad's answer:

基于 Ali 和 Champitoad 的回答:

If you want to try different palettes for the same, you can do this in a few lines:

如果你想尝试不同的调色板,你可以用几行来完成:

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

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

^143 being the number of colours you're sampling

^143 是您采样的颜色数

I picked 143 because the entire range of colours on the colormap comes into play here. What you can do is sample the nth colour every iteration to get the colormap effect.

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

n=20 for i,(x,y) in enumerate(points): plt.scatter(x,y,c=cmap(n*i))

n=20 for i,(x,y) in enumerate(points): plt.scatter(x,y,c=cmap(n*i))

回答by J. Doe

Since the question is How to generate random colors in matplotlib?and as I was searching for an answer concerning pie plots, I think it is worth to put an answer here (for pies)

由于问题是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()

Output

输出

enter image description here

在此处输入图片说明

enter image description here

在此处输入图片说明

回答by Santosh Magadum

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])