web-dev-qa-db-fra.com

Histogramme de tracé avec couleurs extraites de la palette de couleurs

Je veux tracer un histogramme 1D simple où les barres doivent suivre le code couleur d'une carte de couleurs donnée.

Voici une MWE:

import numpy as n
import matplotlib.pyplot as plt

# Random gaussian data.
Ntotal = 1000
data = 0.05 * n.random.randn(Ntotal) + 0.5

# This is  the colormap I'd like to use.
cm = plt.cm.get_cmap('RdYlBu_r')

# Plot histogram.
n, bins, patches = plt.hist(data, 25, normed=1, color='green')

plt.show()

qui produit ceci:

enter image description here

Au lieu que la couleur soit green pour tout l'histogramme, j'aimerais que les colonnes suivent un code de couleur donné par la palette de couleurs définie dans cm et les valeurs de bins. Cela signifierait que les bacs proches de zéro ( non de hauteur mais en position) devraient sembler plus bleus et ceux proches d'un plus rouge, selon la palette de couleurs choisie RdYlBu_r.

Puisque plt.histo ne prend pas un argument cmap, je ne sais pas comment lui dire d’utiliser la palette de couleurs définie dans cm.

29
Gabriel

La commande hist renvoie une liste de correctifs. Vous pouvez donc les parcourir et définir leur couleur comme suit:

import numpy as n
import matplotlib.pyplot as plt

# Random gaussian data.
Ntotal = 1000
data = 0.05 * n.random.randn(Ntotal) + 0.5

# This is  the colormap I'd like to use.
cm = plt.cm.get_cmap('RdYlBu_r')

# Plot histogram.
n, bins, patches = plt.hist(data, 25, normed=1, color='green')
bin_centers = 0.5 * (bins[:-1] + bins[1:])

# scale values to interval [0,1]
col = bin_centers - min(bin_centers)
col /= max(col)

for c, p in Zip(col, patches):
    plt.setp(p, 'facecolor', cm(c))

plt.show()

Pour obtenir les couleurs, vous devez appeler la palette de couleurs avec une valeur comprise entre 0 et 1 . Chiffre obtenu:

enter image description here

34
Bas Swinckels

Une autre approche consiste à utiliser plt.bar qui prend une liste de couleurs. Pour déterminer les largeurs et les hauteurs, vous pouvez utiliser numpy.histogram . Votre palette de couleurs peut être utilisée en recherchant la plage des valeurs x et en les mettant à l'échelle de 0 à 1.

import numpy as n
import matplotlib.pyplot as plt

# Random gaussian data.
Ntotal = 1000
data = 0.05 * n.random.randn(Ntotal) + 0.5

# This is  the colormap I'd like to use.
cm = plt.cm.get_cmap('RdYlBu_r')

# Get the histogramp
Y,X = n.histogram(data, 25, normed=1)
x_span = X.max()-X.min()
C = [cm(((x-X.min())/x_span)) for x in X]

plt.bar(X[:-1],Y,color=C,width=X[1]-X[0])
plt.show()

enter image description here

13
Hooked

Bien que ce ne soit pas ce que vous avez demandé, si quelqu'un d'autre (comme je l'ai fait) est tombé par hasard à la recherche du moyen de faire la coloration par hauteur des bacs au lieu de l'ordre, le code suivant basé sur la réponse de Bas fonctionnerait:

import numpy as np
import matplotlib.pyplot as plt

Ntotal = 1000
data = 0.05 * np.random.randn(Ntotal) + 0.5
cm = plt.cm.get_cmap('RdYlBu_r')

n, bins, patches = plt.hist(data, 25, normed=1, color='green')
# To normalize your values
col = (n-n.min())/(n.max()-n.min())
for c, p in Zip(col, patches):
    plt.setp(p, 'facecolor', cm(c))
plt.show()

 enter image description here

2
Alnilam

J'aime la réponse de Bas Swinckels, mais étant donné que la palette de couleurs cm prend en paramètre une valeur comprise entre 0 et 1, un algorithme plus simple serait comme ceci

import matplotlib.pyplot as plt

Ntotal = 1000
data = 0.05 * n.random.randn(Ntotal) + 0.5

cm = plt.cm.RdBu_r

n, bins, patches = plt.hist(data, 25, normed=1, color='green')
for i, p in enumerate(patches):
    plt.setp(p, 'facecolor', cm(i/25)) # notice the i/25

plt.show()
0
Veiga