web-dev-qa-db-fra.com

Comment générer des couleurs aléatoires dans matplotlib?

Quel est l'exemple trivial de la génération de couleurs aléatoires pour passer aux fonctions de traçage?

J'appelle scatter dans une boucle et je veux que chaque parcelle ait une couleur différente.

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

c: une couleur. c peut être une chaîne de format de couleur unique, ou une séquence de spécifications de couleur de longueur N, ou une séquence de N nombres à mapper sur des couleurs à l'aide de la cmap et de la norme spécifiées via kwargs (voir ci-dessous). Notez que c ne doit pas être une séquence numérique RVB ou RGBA unique, car il est impossible de la distinguer d’un tableau de valeurs à modéliser. c peut être un tableau 2D dans lequel les lignes sont RVB ou RGBA, cependant.

60
John Mee
for X,Y in data:
   scatter(X, Y, c=numpy.random.Rand(3,))
56
Charles Brunet

J'appelle scatter dans une boucle et je veux que chaque parcelle soit d'une couleur différente.

Sur la base de cela et de votre réponse: il me semble que vous voulez réellement n des couleurs distinctes pour vos jeux de données; vous voulez mapper les indices entiers 0, 1, ..., n-1 pour distinguer les couleurs RVB. Quelque chose comme:

mapping index to color

Voici la fonction pour le faire:

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)

Utilisation dans votre pseudo - extrait de code dans la question:

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

J'ai généré le chiffre dans ma réponse avec le code suivant:

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

Testé avec les deux Python 2.7 & matplotlib 1.5, et avec Python 3.5 & matplotlib 2.0. Il fonctionne comme prévu.

112
Ali

en élaborant la réponse de @ john-mee, si vous avez des données arbitrairement longues mais que vous n’avez pas besoin de couleurs strictement uniques:

pour python 2:

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

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

pour python 3:

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

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

cela a l'avantage que les couleurs sont faciles à contrôler et que c'est court.

26
user3240588

Pendant un certain temps, le fait que matplotlib ne génère pas de mappes de couleurs avec des couleurs aléatoires m'ennuyait beaucoup, car il s'agit d'un besoin courant pour les tâches de segmentation et de mise en cluster.

En générant simplement des couleurs aléatoires, nous pouvons en arriver à des couleurs trop claires ou trop sombres, ce qui rend la visualisation difficile. En outre, nous avons généralement besoin que la première ou la dernière couleur soit noire, représentant l’arrière-plan ou les valeurs éloignées. J'ai donc écrit une petite fonction pour mon travail quotidien

Voici le comportement de celui-ci:

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

Generated colormap

Alors vous utilisez simplement new_cmap comme palette de couleurs sur matplotlib:

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

Le code est ici:

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

C'est aussi sur github: https://github.com/delestro/Rand_cmap

20
Delestro

Lorsque moins de 9 jeux de données:

colors = "bgrcmykw"
color_index = 0

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

Puisque la question est How to generate random colors in matplotlib? et comme je cherchais une réponse concernant pie plots, Je pense que cela vaut la peine de mettre une réponse ici (pour 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()

Sortie

enter image description here

enter image description here

8
J. Doe

Voici une version plus concise de la réponse d'ALi donnant une couleur distincte par tracé:

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

Basé sur la réponse de ALi et Champitoad:

Si vous voulez essayer différentes palettes pour la même chose, vous pouvez le faire en quelques lignes:

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

^ 143 étant le nombre de couleurs que vous échantillonnez

J'ai choisi 143 parce que toute la gamme de couleurs de la palette de couleurs entre en jeu ici. Ce que vous pouvez faire est d’échantillonner la nième couleur à chaque itération pour obtenir l’effet de palette de couleurs.

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

3
ai-shwarya

Amélioration de la réponse https://stackoverflow.com/a/14720445/6654512 pour utiliser Python3. Ce code génère parfois des nombres supérieurs à 1 et matplotlib génère une erreur.

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