Show matplotlib colorbar instead of legend for multiple plots with gradually changing colors

I am trying to make a simple plot that shows many curves that belong to a large dataset with a specific order, say plot 1..n. The shape of the curves changes gradually with increasing n. It doesn't matter that readers can see exactly which plot belongs to which value of n, but they have to guess in what order of magnitude n.

So I do something like this:

nValues = range(0,30)
xValues = np.linspace(0,10)
dataset = [(xValues-5-0.5*n)**2 for n in nValues]
colors = {n: colorsys.hsv_to_rgb(hue,0.9,0.7) for n,hue in zip(nValues,np.linspace(0,0.7,len(nValues)))}
for n in nValues:
    plt.plot(dataset[n],color=colors[n])

      

(Just to be clear, this is just an example, my data is actually stored in a nice pandas dataframe.)

enter image description here

Instead of a legend, I would like to add a color bar next to the plot, perhaps a couple of ticks and labels (at least a minimum and a maximum) to indicate which color belongs to which value of n, but I don't know how. I realized that things could be simpler if I actually get my plot color from the ColorMap, but I also don't know how to do this, and I also don't know how to start from there.

Any pointers are appreciated!

+3


source to share


3 answers


Both @tom and @Joe Kington are right: this has been asked before. However, I tried to make a little effort example as related answers. To use colormap (which always displays values ​​from [0,1] to color), you first need to normalize your data. You can use the class for this Normalize

. An instance ScalarMappable

is only required if you intend to create a color bar.

import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import matplotlib.cm as cm
import numpy as np

# your dataset
nValues = np.arange(0,30)
xValues = np.linspace(0,10)
dataset = [(xValues-5-0.5*n)**2 for n in nValues]

# setup the normalization and the colormap
normalize = mcolors.Normalize(vmin=nValues.min(), vmax=nValues.max())
colormap = cm.jet

# plot
for n in nValues:
    plt.plot(dataset[n], color=colormap(normalize(n)))

# setup the colorbar
scalarmappaple = cm.ScalarMappable(norm=normalize, cmap=colormap)
scalarmappaple.set_array(nValues)
plt.colorbar(scalarmappaple)

# show the figure
plt.show()

      



Result:

enter image description here

+3


source


This is almost a duplicate of several other questions. The key is that matplotlib requires an instance ScalarMappable

(usually an image, a scatter plot, etc.) to generate a color map. It's easy to fake if you don't use the build method that creates it. You will need an instance Normalize

to define min / max / scaling / etc in the color palette and an instance Colormap

to define colors.

However, you have an extra wrinkle. You are not using a color code so you need to create one.

Here's an example with a discrete color palette:

import numpy as np
import matplotlib.colors as mcolors
import matplotlib.cm
import matplotlib.pyplot as plt

# Your example...
nvalues = range(0,30)
xvalues = np.linspace(0,10)

hsv2rgb = lambda hue: mcolors.hsv_to_rgb([hue,0.9,0.7])
hues = np.linspace(0, 0.7, len(nvalues))
colors = [hsv2rgb(hue) for hue in hues]

dataset = [(xvalues-5-0.5*n)**2 for n in nvalues]

fig, ax = plt.subplots()
for n in nvalues:
    ax.plot(dataset[n], color=colors[n])

# Fake a ScalarMappable so you can display a colormap
cmap, norm = mcolors.from_levels_and_colors(range(len(nvalues) + 1), colors)
sm = matplotlib.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])

fig.colorbar(sm)

plt.show()

      



enter image description here

And if you prefer a continuous flower card:

import numpy as np
import matplotlib.colors as mcolors
import matplotlib.cm
import matplotlib.pyplot as plt

# Your example...
nvalues = range(0,30)
xvalues = np.linspace(0,10)

hsv2rgb = lambda hue: mcolors.hsv_to_rgb([hue,0.9,0.7])
hues = np.linspace(0, 0.7, len(nvalues))
colors = [hsv2rgb(hue) for hue in hues]

dataset = [(xvalues-5-0.5*n)**2 for n in nvalues]

fig, ax = plt.subplots()
for n in nvalues:
    ax.plot(dataset[n], color=colors[n])

# Fake a ScalarMappable so you can display a colormap
cmap = mcolors.LinearSegmentedColormap.from_list('my_cmap', colors)
norm = mcolors.Normalize(min(nvalues), max(nvalues))
sm = matplotlib.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])

fig.colorbar(sm)

plt.show()

      

enter image description here

+4


source


You need to create a new cmap This code should work:

import matplotlib
import matplotlib.pyplot as plt 
import colorsys
import numpy

nValues = range(30)
xValues = numpy.linspace(0,10)
dataset = [(xValues-5-0.5*n)**2 for n in nValues]
colors  = [colorsys.hsv_to_rgb(hue,0.9,0.7) for hue in numpy.linspace(0.,0.7,30)]

fig = plt.figure()
axe = fig.add_subplot(111)
trh = [axe.plot(dataset[n],color=colors[n]) for n in nValues] # one line loop for plotting the data with associated color
cma = matplotlib.colors.ListedColormap(colors, name='from_list', N=None) # creation of a user cmap
msm = matplotlib.cm.ScalarMappable(cmap=cma) 
msm.set_array(nValues) 
fig.colorbar(msm)
fig.show()

      

+1


source







All Articles