简体   繁体   English

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

[英]How to generate random colors in matplotlib?

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:一种颜色。 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). c 可以是单个颜色格式字符串,或长度为 N 的颜色规范序列,或使用通过 kwargs 指定的 cmap 和范数映射到颜色的 N 个数字序列(见下文)。 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 不应是单个数字 RGB 或 RGBA 序列,因为它与要进行颜色映射的值数组无法区分。 c can be a 2-D array in which the rows are RGB or RGBA, however.然而,c 可以是一个二维数组,其中的行是 RGB 或 RGBA。

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 n distinct colors for your datasets;基于此以及您的回答:在我看来,您实际上希望数据集有n不同的颜色; you want to map the integer indices 0, 1, ..., n-1 to distinct RGB colors.您想将整数索引0, 1, ..., n-1映射到不同的 RGB 颜色。 Something like:就像是:

将索引映射到颜色

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.使用 Python 2.7 和 matplotlib 1.5 以及 Python 3.5 和 matplotlib 2.0 进行了测试。 It works as expected.它按预期工作。

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

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.这样做的优点是颜色易于控制并且很短。

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)

生成的颜色图

Than you just use new_cmap as 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

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

Since the question is How to generate random colors in matplotlib?由于问题是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 )当我正在寻找有关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输出

在此处输入图片说明

在此处输入图片说明

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

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)

^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.我选择了 143,因为颜色图上的整个颜色范围都在这里起作用。 What you can do is sample the nth colour every iteration to get the colormap effect.您可以做的是在每次迭代中对第 n 个颜色进行采样以获得颜色图效果。

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

Improving the answer https://stackoverflow.com/a/14720445/6654512 to work with Python3.改进答案https://stackoverflow.com/a/14720445/6654512以使用 Python3。 That piece of code would sometimes generate numbers greater than 1 and matplotlib would throw an error.这段代码有时会生成大于 1 的数字,而 matplotlib 会抛出错误。

for X,Y in data:
   scatter(X, Y, c=numpy.random.random(3))
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])

If you want to ensure the colours are distinct - but don't know how many colours are needed.如果您想确保颜色不同 - 但不知道需要多少种颜色。 Try something like this.尝试这样的事情。 It selects colours from opposite sides of the spectrum and systematically increases granularity.它从光谱的两侧选择颜色并系统地增加粒度。

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

output输出

Thanks to @Ali for providing the base implementation.感谢@Ali 提供基本实现。

Reproducible results可重复的结果

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

output输出

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

相关问题 如何产生随机的“绿色”颜色 - How to generate random 'greenish' colors matplotlib 中默认的随机颜色 - Random colors by default in matplotlib 生成随机颜色 (RGB) - Generate random colors (RGB) 使用 get_cmap().colors 生成 &#39;N&#39; 个随机颜色 &#39;P&#39; 次的方法。 错误:“LinearSegmentedColormap”对象没有“颜色”属性。 Matplotlib - Method to generate 'N' random colors 'P' times using get_cmap().colors. Error: 'LinearSegmentedColormap' object has no attribute 'colors'. Matplotlib 如何在matplotlib python中的白色背景上以不同的随机颜色显示对象? - How to display objects in different random colors on a white background in matplotlib python? matplotlib.pyplot.tripcolor 如何用随机 RGB 颜色填充三角形? - matplotlib.pyplot.tripcolor how to fill triangles with random RGB colors? 如何在饼图 matplotlib 上生成更多颜色 - How can I generate more colors on pie chart matplotlib 如何使用 Python matplotlib 在两个条形图上生成相同的 colors? - How to generate the same colors across two barcharts using Python matplotlib? 如何将这 20 种随机颜色分配给 Matplotlib 中的 20 个随机 x、y 对? - How to assign these 20 random colors to 20 random x, y pairs in Matplotlib? 如何在matplotlib中为圆圈指定颜色? - How to assign colors to circles in matplotlib?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM