web-dev-qa-db-fra.com

Définition de couleurs différentes pour chaque série dans le nuage de points sur matplotlib

Supposons que j'ai trois ensembles de données:

X = [1,2,3,4]
Y1 = [4,8,12,16]
Y2 = [1,4,9,16]

Je peux disperser cette intrigue:

from matplotlib import pyplot as plt
plt.scatter(X,Y1,color='red')
plt.scatter(X,Y2,color='blue')
plt.show()

Comment puis-je faire cela avec 10 ensembles?

J'ai cherché cela et pourrais trouver n'importe quelle référence à ce que je demande.

Edit: clarifier (j'espère) ma question

Si j'appelle la dispersion plusieurs fois, je ne peux définir que la même couleur pour chaque dispersion. De plus, je sais que je peux définir un tableau de couleurs manuellement, mais je suis sûr qu'il existe un meilleur moyen de le faire. Ma question est alors la suivante: "Comment puis-je automatiquement créer un diagramme de dispersion pour plusieurs ensembles de données, chacun avec une couleur différente?.

Si cela peut aider, je peux facilement attribuer un numéro unique à chaque ensemble de données.

142
Yotam

Je ne sais pas ce que vous entendez par "manuellement". Vous pouvez choisir une palette de couleurs et créer un tableau de couleurs assez facilement:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm

x = np.arange(10)
ys = [i+x+(i*x)**2 for i in range(10)]

colors = cm.Rainbow(np.linspace(0, 1, len(ys)))
for y, c in Zip(ys, colors):
    plt.scatter(x, y, color=c)

Matplotlib graph with different colors

Vous pouvez également créer votre propre cycliste de couleurs à l'aide de itertools.cycle et en spécifiant les couleurs sur lesquelles vous souhaitez effectuer une boucle, à l'aide de next pour obtenir celle de votre choix. Par exemple, avec 3 couleurs:

import itertools

colors = itertools.cycle(["r", "b", "g"])
for y in ys:
    plt.scatter(x, y, color=next(colors))

Matplotlib graph with only 3 colors

À bien y penser, peut-être que c'est plus propre de ne pas utiliser Zip avec le premier aussi:

colors = iter(cm.Rainbow(np.linspace(0, 1, len(ys))))
for y in ys:
    plt.scatter(x, y, color=next(colors))
227
DSM

La méthode normale pour tracer des tracés avec des points de couleurs différentes dans matplotlib consiste à passer une liste de couleurs en tant que paramètre.

Par exemple.:

import matplotlib.pyplot
matplotlib.pyplot.scatter([1,2,3],[4,5,6],color=['red','green','blue'])

3 colors

Lorsque vous avez une liste de listes et que vous voulez les colorier par liste. Je pense que la manière la plus élégante est celle suggérée par @DSM, il suffit de faire une boucle en faisant plusieurs appels à scatter.

Mais si, pour une raison quelconque, vous souhaitez le faire en un seul appel, vous pouvez créer une grande liste de couleurs, avec une liste de compréhension et un peu de division de revêtement de sol:

import matplotlib
import numpy as np

X = [1,2,3,4]
Ys = np.array([[4,8,12,16],
      [1,4,9,16],
      [17, 10, 13, 18],
      [9, 10, 18, 11],
      [4, 15, 17, 6],
      [7, 10, 8, 7],
      [9, 0, 10, 11],
      [14, 1, 15, 5],
      [8, 15, 9, 14],
       [20, 7, 1, 5]])
nCols = len(X)  
nRows = Ys.shape[0]

colors = matplotlib.cm.Rainbow(np.linspace(0, 1, len(Ys)))

cs = [colors[i//len(X)] for i in range(len(Ys)*len(X))] #could be done with numpy's repmat
Xs=X*nRows #use list multiplication for repetition
matplotlib.pyplot.scatter(Xs,Ys.flatten(),color=cs)

All plotted

cs = [array([ 0.5,  0. ,  1. ,  1. ]),
 array([ 0.5,  0. ,  1. ,  1. ]),
 array([ 0.5,  0. ,  1. ,  1. ]),
 array([ 0.5,  0. ,  1. ,  1. ]),
 array([ 0.28039216,  0.33815827,  0.98516223,  1.        ]),
 array([ 0.28039216,  0.33815827,  0.98516223,  1.        ]),
 array([ 0.28039216,  0.33815827,  0.98516223,  1.        ]),
 array([ 0.28039216,  0.33815827,  0.98516223,  1.        ]),
 ...
 array([  1.00000000e+00,   1.22464680e-16,   6.12323400e-17,
          1.00000000e+00]),
 array([  1.00000000e+00,   1.22464680e-16,   6.12323400e-17,
          1.00000000e+00]),
 array([  1.00000000e+00,   1.22464680e-16,   6.12323400e-17,
          1.00000000e+00]),
 array([  1.00000000e+00,   1.22464680e-16,   6.12323400e-17,
          1.00000000e+00])]
42
Lyndon White

Une solution facile

Si vous ne possédez qu'un seul type de collections (par exemple, scatter sans barres d'erreur), vous pouvez également modifier les couleurs après les avoir tracées, ce qui est parfois plus facile à effectuer.

import matplotlib.pyplot as plt
from random import randint
import numpy as np

#Let's generate some random X, Y data X = [ [frst group],[second group] ...]
X = [ [randint(0,50) for i in range(0,5)] for i in range(0,24)]
Y = [ [randint(0,50) for i in range(0,5)] for i in range(0,24)]
labels = range(1,len(X)+1)

fig = plt.figure()
ax = fig.add_subplot(111)
for x,y,lab in Zip(X,Y,labels):
        ax.scatter(x,y,label=lab)

Le seul morceau de code dont vous avez besoin:

#Now this is actually the code that you need, an easy fix your colors just cut and paste not you need ax.
colormap = plt.cm.Gist_ncar #nipy_spectral, Set1,Paired  
colorst = [colormap(i) for i in np.linspace(0, 0.9,len(ax.collections))]       
for t,j1 in enumerate(ax.collections):
    j1.set_color(colorst[t])


ax.legend(fontsize='small')

La sortie vous donne des couleurs différentes même lorsque vous avez plusieurs diagrammes de dispersion dans la même sous-parcelle.

enter image description here

18
G M

Vous pouvez toujours utiliser la fonction plot() comme ceci:

import matplotlib.pyplot as plt

import numpy as np

x = np.arange(10)
ys = [i+x+(i*x)**2 for i in range(10)]
plt.figure()
for y in ys:
    plt.plot(x, y, 'o')
plt.show()

plot as scatter but changes colors

7
Ophir Carmi

Cette question est un peu délicate avant janvier 2013 et matplotlib 1.3.1 (août 2013), qui est la plus ancienne version stable que vous pouvez trouver sur le site Web de matpplotlib. Mais après cela, c'est assez trivial.

Étant donné que la version actuelle de matplotlib.pylab.scatter prend en charge l’affectation: tableau de chaînes de noms de couleurs, tableau de nombres à virgule flottante avec mappe de couleurs, tableau de RVB ou RGBA.

cette réponse est dédiée à la passion sans fin de @ Oxinabox pour corriger sa version de 2013 en 2015.


vous avez deux options pour utiliser la commande scatter avec plusieurs couleurs en un seul appel.

  1. en tant que support de commande pylab.scatter, utilisez le tableau RGBA pour définir la couleur de votre choix;

  2. au début de 2013, il n'y avait aucun moyen de le faire, car la commande ne prend en charge qu'une seule couleur pour l'ensemble de la collection de points de dispersion. Lorsque je réalisais mon projet 10000 lignes, je trouvais une solution générale pour le contourner. c'est donc très collant, mais je peux le faire avec n'importe quelle forme, couleur, taille et transparent. cette astuce pourrait également s'appliquer pour dessiner une collection de chemins, une collection de lignes ....

le code est également inspiré du code source de pyplot.scatter, je viens de dupliquer ce que scatter fait sans le déclencher pour dessiner.

la commande pyplot.scatter renvoie un objet PatchCollection, dans le fichier "matplotlib/collections.py", une variable privée _facecolors dans Collection class et une méthode set_facecolors.

ainsi, chaque fois que vous avez des points de dispersion à dessiner, vous pouvez le faire:

# rgbaArr is a N*4 array of float numbers you know what I mean
# X is a N*2 array of coordinates
# axx is the axes object that current draw, you get it from
# axx = fig.gca()

# also import these, to recreate the within env of scatter command 
import matplotlib.markers as mmarkers
import matplotlib.transforms as mtransforms
from matplotlib.collections import PatchCollection
import matplotlib.markers as mmarkers
import matplotlib.patches as mpatches


# define this function
# m is a string of scatter marker, it could be 'o', 's' etc..
# s is the size of the point, use 1.0
# dpi, get it from axx.figure.dpi
def addPatch_point(m, s, dpi):
    marker_obj = mmarkers.MarkerStyle(m)
    path = marker_obj.get_path()
    trans = mtransforms.Affine2D().scale(np.sqrt(s*5)*dpi/72.0)
    ptch = mpatches.PathPatch(path, fill = True, transform = trans)
    return ptch

patches = []
# markerArr is an array of maker string, ['o', 's'. 'o'...]
# sizeArr is an array of size float, [1.0, 1.0. 0.5...]

for m, s in Zip(markerArr, sizeArr):
    patches.append(addPatch_point(m, s, axx.figure.dpi))

pclt = PatchCollection(
                patches,
                offsets = Zip(X[:,0], X[:,1]),
                transOffset = axx.transData)

pclt.set_transform(mtransforms.IdentityTransform())
pclt.set_edgecolors('none') # it's up to you
pclt._facecolors = rgbaArr

# in the end, when you decide to draw
axx.add_collection(pclt)
# and call axx's parent to draw_idle()
6
Hualin

Cela fonctionne pour moi:

pour chaque série, utilisez un générateur de couleurs RVB aléatoire

c = color[np.random.random_sample(), np.random.random_sample(), np.random.random_sample()]
1
bracoo