Jak wygenerować losowe kolory w matplotlib?

Jaki jest trywialny przykład generowania losowych kolorów do przekazywania do funkcji kreślarskich?

Nazywam scatter wewnątrz pętli i chcę, aby każdy wykres miał inny kolor.

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

C: kolor. c może być ciągiem formatu pojedynczego koloru lub sekwencją specyfikacji kolorów o długości N lub sekwencją n liczb, które mają być odwzorowane na Kolory za pomocą cmap i normy określonych za pomocą kwargs (patrz poniżej). Zauważ, że c nie powinno być pojedynczą liczbową RGB lub RGBA sekwencji, ponieważ jest ona nieodróżnialna od tablicy wartości, które mają być kolormapp. c może być tablicą 2-D, w której wiersze są jednak RGB lub RGBA.

Author: John Mee, 2013-02-06

11 answers

Wzywam scatter wewnątrz pętli i chcę każdy wykres w innym kolorze.

Na tej podstawie i na podstawie Twojej odpowiedzi: wydaje mi się, że naprawdę chcesz n różne kolory {[11] } dla zestawów danych; chcesz zmapować indeksy całkowite 0, 1, ..., n-1 na różne kolory RGB. coś w stylu:

odwzorowanie indeksu na kolor

Oto funkcja, aby to zrobić:

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)

Użycie w Twoim pseudo - fragment kodu w pytaniu:

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

I wygenerowałem rysunek w mojej odpowiedzi o następującym kodzie:

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()
Testowane z Pythonem 2.7 i matplotlib 1.5 oraz z Pythonem 3.5 i matplotlib 2.0. Działa zgodnie z oczekiwaniami.
 145
Author: Ali,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-22 14:45:17
for X,Y in data:
   scatter(X, Y, c=numpy.random.rand(3,))
 79
Author: Charles Brunet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-12 07:49:51

Odpowiedź @ john-mee, jeśli masz dowolnie długie dane, ale nie potrzebujesz ściśle unikalnych kolorów:

Dla Pythona 2:

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

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

Dla Pythona 3:

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

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

Ma to tę zaletę, że kolory są łatwe do kontrolowania i że są krótkie.

 31
Author: user3240588,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-06 12:04:13

Przez jakiś czas byłem naprawdę zirytowany faktem, że matplotlib nie generuje colormaps z przypadkowymi kolorami, ponieważ jest to powszechna potrzeba segmentacji i grupowania zadań.

Generując tylko losowe kolory możemy skończyć z tymi, które są zbyt jasne lub zbyt ciemne, co utrudnia wizualizację. Również, zwykle musimy pierwszy lub ostatni kolor być czarny, reprezentujący tło lub odstających. Więc napisałem małą funkcję do mojej codziennej pracy

Oto zachowanie it:

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

Wygenerowana colormap

Niż po prostu użyć new_cmap jako colormap na matplotlib:

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

Kod jest tutaj:

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

Jest również na GitHubie: https://github.com/delestro/rand_cmap

 28
Author: Delestro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-16 20:06:10

Gdy mniej niż 9 zbiorów danych:

colors = "bgrcmykw"
color_index = 0

for X,Y in data:
    scatter(X,Y, c=colors[color_index])
    color_index += 1
 15
Author: John Mee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-06 02:20:37

Ponieważ pytanie jest How to generate random colors in matplotlib? i ponieważ szukałem odpowiedzi dotyczącej pie plots, myślę, że warto umieścić odpowiedź tutaj (dla 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()

Wyjście

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka

 12
Author: J. Doe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-24 14:20:20

Oto bardziej zwięzła Wersja odpowiedzi Ali, dająca jeden wyraźny kolor na fabułę :

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))
 9
Author: Champitoad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-07 01:48:43

Na podstawie odpowiedzi Ali i Champitoada:

Jeśli chcesz wypróbować różne palety dla tego samego, możesz to zrobić w kilku linijkach:

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

^143 to liczba kolorów, które próbkujesz

Wybrałem 143, ponieważ cała gama kolorów na colormap wchodzi w grę tutaj. Co możesz zrobić, to próbkować n-ty kolor każdej iteracji, aby uzyskać efekt colormap.

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

 4
Author: ai-shwarya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-24 03:24:15
 2
Author: Ale Solano,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-03 12:13:38
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])
 1
Author: Santosh Magadum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-16 11:35:15

Jeśli chcesz mieć pewność, że kolory są wyraźne - ale nie wiesz, ile kolorów jest potrzebnych. Spróbuj czegoś takiego. Dobiera kolory z przeciwległych stron spektrum i systematycznie zwiększa ziarnistość.

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

Wyjście

Podziękowania dla @ Ali za dostarczenie podstawowej implementacji.

 1
Author: Johan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-07 10:38:13