J'essaie de créer une barre de couleurs discrète pour un nuage de points dans matplotlib
J'ai mes données x, y et pour chaque point une valeur de balise entière que je veux être représentée avec une couleur unique, par exemple
plt.scatter(x, y, c=tag)
généralement la balise sera un entier compris entre 0 et 20, mais la plage exacte peut changer
jusqu'à présent, je viens d'utiliser les paramètres par défaut, par exemple
plt.colorbar()
ce qui donne une gamme continue de couleurs. Idéalement, je voudrais un ensemble de n couleurs discrètes (n = 20 dans cet exemple). Encore mieux serait d'obtenir une valeur de balise de 0 pour produire une couleur grise et de 1 à 20 pour être coloré.
J'ai trouvé des scripts de `` livres de recettes '' mais ils sont très compliqués et je ne peux pas penser qu'ils sont la bonne façon de résoudre un problème apparemment simple
Réponses:
Vous pouvez créer une barre de couleurs discrète personnalisée assez facilement en utilisant un BoundaryNorm comme normalisateur pour votre dispersion. Le peu bizarre (dans ma méthode) fait apparaître 0 comme gris.
Pour les images, j'utilise souvent cmap.set_bad () et je convertis mes données en un tableau masqué numpy. Ce serait beaucoup plus facile de rendre 0 gris, mais je ne pouvais pas faire fonctionner cela avec le scatter ou le cmap personnalisé.
Comme alternative, vous pouvez créer votre propre cmap à partir de zéro, ou lire une cmap existante et remplacer uniquement certaines entrées spécifiques.
Personnellement, je pense qu'avec 20 couleurs différentes, il est un peu difficile de lire la valeur spécifique, mais cela dépend de vous bien sûr.
la source
plt.colorbar.ColorbarBase
jette une erreur. Utilisationmpl.colorbar.ColorbarBase
N-1
encmap = mpl.colors.LinearSegmentedColormap.from_list('Custom cmap', cmaplist, cmap.N-1)
. Sinon, les couleurs ne sont pas également réparties dans les bacs et vous avez un problème de barrière de clôture.q=np.arange(0.0, 1.01, 0.1) cmap = mpl.cm.get_cmap('jet') cmaplist = [cmap(x) for x in q] cmap = mpl.colors.LinearSegmentedColormap.from_list('Custom cmap', cmaplist, len(q)-1) norm = mpl.colors.BoundaryNorm(q, cmap.N)
N-1
, vous avez peut-être raison, mais je ne peux pas le reproduire avec mon exemple. Vous pouvez éviter l' argumentLinearSegmentedColormap
(et sonN
argument) en utilisant unListedColormap
. La documentation s'est beaucoup améliorée depuis '13, voir par exemple: matplotlib.org/3.1.1/tutorials/colorsVous pouvez suivre cet exemple :
qui produit l'image suivante:
la source
Les réponses ci-dessus sont bonnes, sauf qu'elles n'ont pas le placement correct des coches sur la barre de couleurs. J'aime avoir les coches au milieu de la couleur pour que le mappage nombre -> couleur soit plus clair. Vous pouvez résoudre ce problème en modifiant les limites de l'appel matshow:
la source
set_ticklabels(...)
ne doit être utilisé que pour contrôler le formatage des étiquettes (par exemple, nombre décimal, etc.). Si les données sont vraiment discrètes, vous ne remarquerez peut-être aucun problème. S'il y a du bruit dans le système (par exemple 2 -> 1.9), cet étiquetage incohérent entraînera une barre de couleurs trompeuse et incorrecte.Pour définir une valeur supérieure ou inférieure à la plage de la palette de couleurs, vous souhaiterez utiliser les méthodes
set_over
etset_under
de la palette de couleurs. Si vous voulez marquer une valeur particulière, masquez-la (c'est-à-dire créez un tableau masqué) et utilisez laset_bad
méthode. (Consultez la documentation de la classe de palette de couleurs de base: http://matplotlib.org/api/colors_api.html#matplotlib.colors.Colormap )Il semble que vous vouliez quelque chose comme ceci:
la source
Ce sujet est déjà bien couvert mais je voulais ajouter quelque chose de plus spécifique: je voulais être sûr qu'une certaine valeur serait mappée à cette couleur (pas à n'importe quelle couleur).
Ce n'est pas compliqué mais comme cela m'a pris du temps, cela pourrait aider les autres à ne pas perdre autant de temps que moi :)
la source
pos
ce qui concerne je ne suis pas tout à fait sûr de savoir pourquoi il est ici mais c'est demandé par le FuncFormatter () ... Peut-être que quelqu'un d'autre pourra nous éclairer à ce sujet!J'ai étudié ces idées et voici ma valeur de cinq cents. Cela évite d'appeler
BoundaryNorm
et de spécifiernorm
comme argument descatter
etcolorbar
. Cependant, je n'ai trouvé aucun moyen d'éliminer l'appel plutôt longmatplotlib.colors.LinearSegmentedColormap.from_list
.Un certain contexte est que matplotlib fournit des cartes de couleurs dites qualitatives, destinées à être utilisées avec des données discrètes.
Set1
, par exemple, a 9 couleurs faciles à distinguer ettab20
peut être utilisé pour 20 couleurs. Avec ces cartes, il peut être naturel d'utiliser leurs n premières couleurs pour colorer les nuages de points avec n catégories, comme le fait l'exemple suivant. L'exemple produit également une barre de couleurs avec n couleurs discrètes étiquetées de manière appropriée.qui produit l'image ci-dessous. Le
n
dans l'appel àSet1
spécifie les premièresn
couleurs de cette palette de couleurs, et la dernièren
dans l'appel àfrom_list
spécifie de construire une carte avec desn
couleurs (la valeur par défaut étant 256). Afin de définircm
comme palette de couleurs par défaut avecplt.set_cmap
, j'ai trouvé qu'il était nécessaire de lui donner un nom et de l'enregistrer, à savoir:la source
Je pense que vous voudriez regarder colors.ListedColormap pour générer votre palette de couleurs, ou si vous avez juste besoin d'une palette de couleurs statique, j'ai travaillé sur une application qui pourrait vous aider.
la source