Plot histogram with colors taken from colormap

46,864

Solution 1

The hist command returns a list of patches, so you can iterate over them and set their color like so:

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

To get the colors, you need to call the colormap with a value between 0 and 1. Resulting figure:

enter image description here

Solution 2

An alternative approach is to use plt.bar which takes in a list of colors. To determine the widths and heights you can use numpy.histogram. Your colormap can be used by finding the range of the x-values and scaling them from 0 to 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

Solution 3

While it isn't what you asked for, if someone else stumbles across this (like I did) looking for the way to do the coloration by height of the bins instead of order, the following code based on Bas's answer would work:

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

Solution 4

I like Bas Swinckels answer, but given that the colormap cm take as parameter a value between 0 and 1, a simpler algorithm would be like this

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()
Share:
46,864
Gabriel
Author by

Gabriel

Updated on July 30, 2022

Comments

  • Gabriel
    Gabriel almost 2 years

    I want to plot a simple 1D histogram where the bars should follow the color-coding of a given colormap.

    Here's an 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()
    

    which outputs this:

    enter image description here

    Instead of the color being green for the entire histogram, I'd like the columns to follow a color-coding given by the colormap defined in cm and the values of the bins. This would mean that bins closer to zero (not in height but in position) should look bluer and those closer to one redder, according to the chosen colormap RdYlBu_r.

    Since plt.histo doesn't take a cmap argument I don't know how to tell it to use the colormap defined in cm.

  • Hooked
    Hooked about 10 years
    I hope you don't mind - imgur is not blocked at my work so I went ahead and added your picture. I think both approaches are good solutions to this question!
  • Gabriel
    Gabriel about 10 years
    Mmm if the image is correct then the code is not doing what I need. The color-coding is associated with the bars heigth and I need it associated with the bins value. See @Hooked answer's to see what I mean.
  • Hooked
    Hooked about 10 years
    @Gabriel It's true that Bas's answer does not match the color-coding scheme you want - but it's important to take away that we are using different methods, setp versus bar. Each one has its advantages, the mapping of the colorbar could easily be modified in this answer to get the one you were looking for.
  • Hooked
    Hooked about 10 years
    @BasSwinckels You might be able to use the site url through a proxy (say google translate) to at least view the images, if not edit them.
  • Gabriel
    Gabriel about 10 years
    Although @Hooked answer is also very good I'm marking this one as accepted since it follows the code provided in the question more closely. Thank you both!