aprendiz
aprendiz

Reputation: 611

Bar chart in matplotlib using a colormap

I have a df with two columns:

I also have a colormap with four different colors that I made myself and it's a ListedColorMap object.

I want to create a bar chart with the four categories (days of the week) in the x axis and their corresponding values in the y axis. At the same time, I want each bar to have a different color using my colormap.

This is the code I used to build my bar chart:

def my_barchart(my_df, my_cmap):
  fig = plt.figure()
  ax = fig.add_axes([0,0,1,1])
  ax.bar(my_df['days'], my_df['y'], color=my_cmap)
  return fig

However, I get the following error: "object of type 'ListedColormap' has no len()", so it seems that I'm not using my_cmap correctly.

If I remove that from the function and run it, my bar chart looks ok, except that all bars have the same color. So my question is: what is the right way to use a colormap with a bar chart?

Upvotes: 22

Views: 43328

Answers (2)

aprendiz
aprendiz

Reputation: 611

Okay, I found a way to do this without having to scale my values:

def my_barchart(my_df, my_cmap):
  fig = plt.figure()
  ax = fig.add_axes([0,0,1,1])
  ax.bar(my_df['days'], my_df['y'], color=my_cmap.colors)
  return fig

Simply adding .colors after my_cmap works!

Upvotes: 15

Jake Levi
Jake Levi

Reputation: 1740

The color argument wants either a string or an RGB[A] value (it can be a single colour, or a sequence of colours with one for each data point you are plotting). Colour maps are typically callable with floats in the range [0, 1].

So what you want to do is take the values you want for the colours for each bar, scale them to the range [0, 1], and then call my_cmap with those rescaled values.

So, say for example you wanted the colours to correspond to the y values (heights of the bars), then you should modify your code like this (assumes you have called import numpy as np earlier on):

def my_barchart(my_df, my_cmap):
    rescale = lambda y: (y - np.min(y)) / (np.max(y) - np.min(y))

    fig = plt.figure()
    ax = fig.add_axes([0,0,1,1])
    ax.bar(my_df['days'], my_df['y'], color=my_cmap(rescale(my_df['y'])))
    return fig

Here is a self-contained minimal example of using the color argument with the output from a cmap:

import matplotlib.pyplot as plt
import numpy as np

x = np.array([1, 2, 3])
y = np.array([4, 5, 6])

my_cmap = plt.get_cmap("viridis")
rescale = lambda y: (y - np.min(y)) / (np.max(y) - np.min(y))

plt.bar(x, y, color=my_cmap(rescale(y)))
plt.savefig("temp")

Output:

enter image description here

Upvotes: 21

Related Questions