web-dev-qa-db-fra.com

Comment donner à un graphique à barres pandas / matplotlib des couleurs personnalisées

Je viens juste de commencer à utiliser pandas/matplotlib en remplacement d'Excel pour générer des graphiques à barres empilées. Je rencontre un problème

(1) Il n'y a que 5 couleurs dans la palette de couleurs par défaut, donc si j'ai plus de 5 catégories, les couleurs se répètent. Comment puis-je spécifier plus de couleurs? Idéalement, un dégradé avec une couleur de début et une couleur de fin et un moyen de générer dynamiquement n couleurs entre?

(2) les couleurs ne sont pas très attrayantes visuellement. Comment spécifier un ensemble personnalisé de n couleurs? Ou bien, un dégradé fonctionnerait également.

Voici un exemple illustrant les deux points ci-dessus:

  4 from matplotlib import pyplot
  5 from pandas import *
  6 import random
  7 
  8 x = [{i:random.randint(1,5)} for i in range(10)]
  9 df = DataFrame(x)
 10 
 11 df.plot(kind='bar', stacked=True)

Et la sortie est la suivante:

enter image description here

64
vasek1

Vous pouvez spécifier l'option color sous forme de liste directement dans la fonction plot.

from matplotlib import pyplot as plt
from itertools import cycle, islice
import pandas, numpy as np  # I find np.random.randint to be better

# Make the data
x = [{i:np.random.randint(1,5)} for i in range(10)]
df = pandas.DataFrame(x)

# Make a list by cycling through the colors you care about
# to match the length of your data.
my_colors = list(islice(cycle(['b', 'r', 'g', 'y', 'k']), None, len(df)))

# Specify this list of colors as the `color` option to `plot`.
df.plot(kind='bar', stacked=True, color=my_colors)

Pour définir votre propre liste personnalisée, vous pouvez effectuer certaines des opérations suivantes ou simplement rechercher les techniques Matplotlib permettant de définir un élément de couleur à l'aide de ses valeurs RVB, etc. Vous pouvez vous rendre aussi compliqué que vous le souhaitez.

my_colors = ['g', 'b']*5 # <-- this concatenates the list to itself 5 times.
my_colors = [(0.5,0.4,0.5), (0.75, 0.75, 0.25)]*5 # <-- make two custom RGBs and repeat/alternate them over all the bar elements.
my_colors = [(x/10.0, x/20.0, 0.75) for x in range(len(df))] # <-- Quick gradient example along the Red/Green dimensions.

Le dernier exemple me donne le simple dégradé de couleurs suivant:

enter image description here

Je n'ai pas joué assez longtemps avec ce logiciel pour comprendre comment forcer la légende à saisir les couleurs définies, mais je suis sûr que vous pouvez le faire.

En général, cependant, un conseil important consiste à utiliser directement les fonctions de Matplotlib. Les appeler de Pandas est correct, mais je trouve que vous obtenez de meilleures options et de meilleures performances en les appelant directement de Matplotlib.

91
ely

J'ai trouvé le moyen le plus simple consiste à utiliser le paramètre colormap dans .plot() avec l'un des dégradés de couleurs prédéfinis:

df.plot(kind='bar', stacked=True, colormap='Paired')

enter image description here

Vous pouvez trouver un grand liste des tables de couleurs prédéfinies ici .

colormaps

41
Alexandre

Pour une réponse plus détaillée sur la création de vos propres cartes de couleurs, je suggère fortement de visiter cette page

Si cette réponse vous demande trop de travail, vous pouvez rapidement créer votre propre liste de couleurs et les transmettre au paramètre color. Toutes les couleurs sont dans le module cm matplotlib. Obtenons une liste de 30 valeurs de couleur RVB (plus alpha) à partir de la palette de couleurs Inferno inversée. Pour ce faire, commencez par obtenir la palette de couleurs et transmettez-lui une séquence de valeurs comprise entre 0 et 1. Ici, nous utilisons np.linspace pour créer 30 valeurs égales entre 0,4 et 0,8 qui représentent cette partie de la palette de couleurs.

from matplotlib import cm
color = cm.inferno_r(np.linspace(.4,.8, 30))
color

array([[ 0.865006,  0.316822,  0.226055,  1.      ],
       [ 0.851384,  0.30226 ,  0.239636,  1.      ],
       [ 0.832299,  0.283913,  0.257383,  1.      ],
       [ 0.817341,  0.270954,  0.27039 ,  1.      ],
       [ 0.796607,  0.254728,  0.287264,  1.      ],
       [ 0.775059,  0.239667,  0.303526,  1.      ],
       [ 0.758422,  0.229097,  0.315266,  1.      ],
       [ 0.735683,  0.215906,  0.330245,  1.      ],
       .....

Ensuite, nous pouvons utiliser ceci pour tracer - en utilisant les données de l'article original:

import random
x = [{i:random.randint(1,5)} for i in range(30)]
df = pd.DataFrame(x)
df.plot(kind='bar', stacked=True, color=color, legend=False, figsize=(12,4))

enter image description here

11
Ted Petrou