Plotting bar charts with a colormap legend - python

Consider the following:
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
y = np.array([1, 4, 3, 2, 7, 11])
colors = cm.hsv(y / float(max(y)))
plot = plt.scatter(y, y, c = y, cmap = 'hsv')
plt.clf()
plt.colorbar(plot)
plt.bar(range(len(y)), y, color = colors)
plt.show()
I want to colormap legend to appear on the top right of the graph (much smaller of course). My image at the moment looks rather clunky as the colormap is clashing somewhat with the actual bars.
Thanks.

Following this answer:
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
y = np.array([1, 4, 3, 2, 7, 11])
colors = cm.hsv(y / float(max(y)))
fig, ax = plt.subplots()
plot = ax.scatter(y, y, c = y, cmap = 'hsv')
plt.cla()
ax.bar(range(len(y)), y, color = colors)
cbaxes = inset_axes(ax, width="30%", height="3%", loc=2)
plt.colorbar(plot, cax=cbaxes, orientation='horizontal', ticks=[0,2,4,6,8,10])
I use plt.subplots to easily reference the Axes (ax). You can move the color bar and change its size by editing the last 2 lines (for instance changing loc can set which corner you want the colorbar to be in).

Related

How to add colorbar in matplotlib

I don't really understand the documentation on colorbar I wanted explanation on a basic example. So below I am plotting exp(-x*a) for a={1, 2, 3, 4}. How do I add color bar with the values of a.
import numpy as np
import matplotlib.pyplot as plt
def func(x,a):
return np.exp(-x*a)
x = np.linspace(0, 5)
for a in range(1,5):
plt.plot(func(x,a))
plt.show()
I'm confused with imshow, subplot, ax.
Colour schemes are defined in the range 0 to 1, therefore you first need to normalise your values (0 to 5) to the range 0 to 1. Then you can pull the colour from the colormap. At the end you have to plot a color bar using the colour map and norm that you chose on the axis you used for plotting.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm, colors
def func(x, a):
return np.exp(-x * a)
x = np.linspace(0, 5)
fig, ax = plt.subplots()
# define color map
cmap = cm.get_cmap("Spectral")
# need to normalize because color maps are defined in [0, 1]
norm = colors.Normalize(0, 5)
for a in range(1, 5):
ax.plot(x, func(x, a),
color=cmap(norm(a))) # get color from color map
# plot colorbar
fig.colorbar(cm.ScalarMappable(norm=norm, cmap=cmap), ax=ax)
plt.show()
The plot looks like this:

How to have a image as the plot face (the outer border) in matplotlib?

I know I can change the color using fig.patch.set_facecolor("#ccdece") but how do I have an image instead of a solid color? Like using img = plt.imread() and ax.imshow(img) but for the outer border.
Any help is welcome.
You can create a dummy ax for the full size of the surrounding figure and add an image to that ax. Giving the ax a low enough zorder makes sure it appears behind the actual plots.
For an additional effect, the facecolor of the actual plots can be made semi-transparent.
Here is an example starting from a stock image.
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import numpy as np
imageFile = cbook.get_sample_data('ada.png')
image = plt.imread(imageFile)
fig, ax = plt.subplots(figsize=(6, 8))
bg_ax = fig.add_axes([0, 0, 1, 1], zorder=-1)
bg_ax.axis('off')
bg_ax.imshow(image)
t = np.linspace(0, 4 * np.pi, 200)
x = 2 * np.cos(t / 2)
y = np.sin(t)
ax.plot(x, y)
ax.set_facecolor('#FFFFFFEE')
plt.show()

Matplotlib: Add colorbar to non-mappable object

I have a series of lines representing the change of a variable; each with a unique color. For that reason I want to add a colorbar next to the plot. The desired output is shown below.
The problem is that plot is a non-mappable object, i.e. the colorbar has to be added manually. I consider my current solution (below) sub-optimal as it involves size parameters of which I have no interest in controlling. I'd prefer a similar solution as for a mappable object (example below current solution).
Desired output
Current solution
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
x = np.linspace(0, 5, 100)
N = 20
cmap = plt.get_cmap('jet',N)
fig = plt.figure(figsize=(8,6))
ax1 = fig.add_axes([0.10,0.10,0.70,0.85])
for i,n in enumerate(np.linspace(0,2,N)):
y = np.sin(x)*x**n
ax1.plot(x,y,c=cmap(i))
plt.xlabel('x')
plt.ylabel('y')
ax2 = fig.add_axes([0.85,0.10,0.05,0.85])
norm = mpl.colors.Normalize(vmin=0,vmax=2)
cb1 = mpl.colorbar.ColorbarBase(ax2,cmap=cmap,norm=norm,orientation='vertical')
plt.show()
Desired solution
(obviously replacing imshow)
fig,ax = plt.subplots()
cax = ax.imshow(..)
cbar = fig.colorbar(cax,aspect=10)
plt.show()
You may define your own ScalarMappable and use it just as if it was present in the plot.
(Note that I changed the numbero f colors to 21 to have nice spacings of 0.1)
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
x = np.linspace(0, 5, 100)
N = 21
cmap = plt.get_cmap('jet',N)
fig = plt.figure(figsize=(8,6))
ax1 = fig.add_axes([0.10,0.10,0.70,0.85])
for i,n in enumerate(np.linspace(0,2,N)):
y = np.sin(x)*x**n
ax1.plot(x,y,c=cmap(i))
plt.xlabel('x')
plt.ylabel('y')
norm = mpl.colors.Normalize(vmin=0,vmax=2)
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])
plt.colorbar(sm, ticks=np.linspace(0,2,N),
boundaries=np.arange(-0.05,2.1,.1))
plt.show()

Defining colors of Matplotlib 3D bar plot

I can't figure out the right way to set a cmap (or colors) for a 3d bar plot in matplotlib in my iPython notebook. I can setup my chart correctly (28 x 7 labels) in the X and Y plane, with some random Z values. The graph is hard to interpret, and one reason is that the default colors for the x_data labels [1,2,3,4,5] are all the same.
Here is the code:
%matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as npfig = plt.figure(figsize=(18,12))
ax = fig.add_subplot(111, projection='3d')
x_data, y_data = np.meshgrid(np.arange(5),np.arange(3))
z_data = np.random.rand(3,5).flatten()
ax.bar3d(x_data.flatten(),
y_data.flatten(),np.zeros(len(z_data)),1,1,z_data,alpha=0.10)
Which produces the following chart:
I don't want to define the colors manually for the labels x_data. How can I set up different 'random' cmap colors for each of the labels in x_data, still keeping the
ax.bar3d
parameter? Below is a variation using
ax.bar
and different colors, but what I need is ax.bar3d.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(figsize=(18,12))
ax = fig.add_subplot(111, projection='3d')
x_data, y_data = np.meshgrid(np.arange(5),np.arange(3))
z_data = np.random.rand(3,5)
colors = ['r','g','b'] # colors for every line of y
# plot colored 3d bars
for i in xrange(3): # cycle though y
# I multiply one color by len of x (it is 5) to set one color for y line
ax.bar3d(x_data[i], y_data[i], z_data[i], 1, 1, z_data[i], alpha=0.1, color=colors[i]*5)
# or use random colors
# ax.bar3d(x_data[i], y_data[i], z_data[i], 1, 1, z_data[i], alpha=0.1, color=[np.random.rand(3,1),]*5)
plt.show()
Result:

Matplotlib: displaying only unique labels for the legend

Let's say I have an array of X (X.shape = [N, 2]) and labels (labels.shape = N).
I want to produce a scatter of X[:,0], X[:,1], color corresponding to the label, and only the unique labels displayed.
Code:
import numpy as np
from numpy.random import rand
import matplotlib
from matplotlib import pyplot as plt
%matplotlib inline
import seaborn as sns
sns.set(context='poster', style='dark')
X = rand(500)
Y = rand(500)
labels = np.round(rand(500)*4).astype(int)
print(np.unique(labels)) # array([0, 1, 2, 3, 4])
plt.scatter(X, Y, c=labels, cmap='rainbow') # this does what I want minus the labels
plt.scatter(X, Y, c=labels, cmap='rainbow', label=labels)
plt.legend(loc='best') # this produces 500 labels instead of 5
You could plot each label individually. You need to choose its color from the cmap, which you need to normalize to your labels first.
import numpy as np
from numpy.random import rand
import matplotlib.pyplot as plt
from matplotlib import cm, colors
%matplotlib inline
import seaborn as sns
sns.set(context='poster', style='dark')
X = rand(500)
Y = rand(500)
labels = np.round(rand(500)*4).astype(int)
unique_labels=np.unique(labels) # array([0, 1, 2, 3, 4])
norm = colors.Normalize(vmin=unique_labels[0], vmax=unique_labels[-1])
m = cm.ScalarMappable(norm=norm, cmap=cm.rainbow)
for label in np.unique(labels):
color = m.to_rgba(label)
plt.scatter(X[labels==label], Y[labels==label], c=color, label=label)
plt.legend(loc='best')
produces this (without seaborn, as I don't have that installed, but you get the idea):

Categories

Resources