How to get part of a colormap

AlexJJ :

I'm plotting some curves from a dataframe "self.data" in a class. Each column of the dataframe is a curve and the column name is written at the end of the line.

I made this program to do so:

cmap = plt.cm.get_cmap('brg', len(self.data.columns)+1)

for i in range(len(self.data.columns)): #plot curves and add legend
        self.courbe.plot(self.data[self.data.columns[i]],c=cmap(i))

        angle=20
        self.courbe.annotate(self.data.columns[i], 
                    xy= (max(self.data.index),self.data.at[max(self.data.index),self.data.columns[i]]),
                    textcoords='offset points',
                    xytext=(2, 0),
                    va='bottom',
                    rotation=angle,c=cmap(i))

So i used the "brg" colormap but i'd like to use only a part of this color map ( for example removing the light green part).

I tried some proposed solutions on stackoverflow like how to extract a subset of a colormap as a new colormap in matplotlib? but all curves were in the same color. Do someone knows another way to do that?

Thanks and have a good day :)

JohanC :

A norm is used to map a range of numbers towards the range 0..1 needed by the colormap. We can create a special norm to get the desired effect.

A norm depends on a vmin, the lowest index, and a vmax, the highest index. vmin would be mapped to 0 and vmax to 1.

Choosing an upper and lower color (each between 0 and 1), for example upper=0.9 to stop at the light greens in bgr. And lower=0 to get all the colors up to the dark blue.

A formula finds the vmin and vmax which would map index i=0 to the lower_color and index i=num_colors-1 to the upper_color. The formula follows from the unique linear equation which maps:

  • 0 to lower_color
  • num_colors - 1 to upper_color
  • vmin to 0
  • vmax to 1

You find the color index for a value i=0..num_colors-1 as norm(i) and the corresponding color as cmap(norm(i)).

import matplotlib.pyplot as plt
import matplotlib as mpl

cmap = plt.cm.get_cmap('brg')

# between 0 and 1, 0 for the leftmost color of the range, 1 for the rightmost, upper > lower
upper_color = 0.8
lower_color = 0.3
num_colors =  20 # len(self.data.columns)
factor = (num_colors - 1)/(upper_color - lower_color)
norm = mpl.colors.Normalize(vmin=-lower_color*factor, vmax=(1 - lower_color)*factor)

for i in range(num_colors):
    plt.plot([0, 1], [0, i], c=cmap(norm(i)))

plt.show()

An example with the brg map and choosing colors between 0.3 and 0.8, just to show how it works. For reference, there is a colorbar with the same limits applied. And a full colorbar for brg.

example plot

The colorbars were generated as follows:

c_map_ax = plt.gcf().add_axes([0.84, 0.1, 0.02, 0.8])
mpl.colorbar.ColorbarBase(c_map_ax, cmap=cmap, orientation='vertical')
c_map_ax.axes.set_ylim(lower_color, upper_color)
c_map_ax2 = plt.gcf().add_axes([0.92, 0.1, 0.02, 0.8])
mpl.colorbar.ColorbarBase(c_map_ax2, cmap=cmap, orientation='vertical')
plt.subplots_adjust(right=0.8)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=11616&siteId=1