Подтвердить что ты не робот

Как генерировать случайные цвета в matplotlib?

Какой тривиальный пример создания случайных цветов для перехода к построению функций?

Я вызываю разброс внутри цикла и хочу, чтобы каждый график имел другой цвет.

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

с: цвет. c может быть одиночная строка формата цвета или последовательность цветовых характеристик длины N или последовательность из N чисел, которые должны отображаться в цвета с использованием cmap и нормы, указанной через kwargs (см. ниже). Обратите внимание, что c не должно быть одиночной числовой RGB или RGBA-последовательностью, потому что это неотличимо от массива значений, которые должны быть сопоставлены. c может быть двухмерным массивом, в котором строки RGB или RGBA, однако.

4b9b3361

Ответ 1

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

Ответ 2

Я вызываю разброс внутри цикла и хочу, чтобы каждый график имел другой цвет.

Основываясь на этом и на вашем ответе: мне кажется, что вы действительно хотите n отличные цвета для ваших наборов данных; вы хотите сопоставить целые индексы 0, 1, ..., n-1 с различными цветами RGB. Что-то вроде:

mapping index to color

Вот как это сделать:

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. Он работает как ожидалось.

Ответ 3

подробный ответ @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))

Преимущество заключается в том, что цвета легко контролировать и они короткие.

Ответ 4

Некоторое время меня действительно раздражал тот факт, что matplotlib не генерирует цветовые карты со случайными цветами, так как это общая потребность в задачах сегментации и кластеризации.

Просто генерируя случайные цвета, мы можем закончить тем, что слишком яркие или слишком темные, что затрудняет визуализацию. Кроме того, обычно нам нужен первый или последний цвет, чтобы быть черным, представляя фон или выбросы. Итак, я написал небольшую функцию для моей повседневной работы

Вот поведение этого:

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

Generated colormap

Чем вы просто используете 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

Ответ 5

При использовании менее 9 наборов данных:

colors = "bgrcmykw"
color_index = 0

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

Ответ 6

Так как вопрос в том, 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()

Выход

enter image description here

enter image description here

Ответ 7

Вот более краткий вариант ответа Али, дающий один цвет за каждый сюжет:

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

Ответ 8

На основании ответов Али и Champitoad:

Если вы хотите попробовать разные палитры для одного и того же, вы можете сделать это в нескольких строках:

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

^ 143 - количество выбранных цветов

Я выбрал 143, потому что здесь используется весь диапазон цветов в цветовой палитре. То, что вы можете сделать, - это образец n-го цвета для каждой итерации, чтобы получить эффект colormap.

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

Ответ 9

Улучшение ответа fooobar.com/questions/164888/... для работы с Python3. Эта часть кода иногда генерирует числа больше 1, а matplotlib выдает ошибку.

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

Ответ 10

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