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:
Related
I have a heatmap that contains only absolute values of -1, 0 and 1
import random
import numpy as np
import matplotlib
import seaborn as sb
import matplotlib.pyplot as plt
array = []
for x in range(10):
array.append(random.choices([-1,0, 1], k = 5))
array = np.array(array)
heatmap = sb.heatmap(array, cbar_kws={'ticks': [-1, 0 , 1]}, cmap = ["red", "grey", "green"])
plt.show()
is it possible to remove the colorbar and replace it by three different collored boxes and a custom label, like you would expect in the legend of a barplot?
I.E. a red box and the word "No" next to it, a grey box and the word "N/A" next to it and a green box with the word "yes" next to it
You can do it manually using matplotlib. To create the boxes, we do a scatter plot with squares for each color but without data, so they won't show up. We save the return value of those scatter plots as handles to pass to the legend. We then grab the matplotlib figure object from the heatmap variable, which contains the axis on which the plot is located. There, we create a legend with the custom handles and labels.
Calling subplots_adjust on that figure, we make room for the legend on the right.
import random
import numpy as np
import matplotlib
import seaborn as sb
import matplotlib.pyplot as plt
array = []
for x in range(10):
array.append(random.choices([-1,0, 1], k = 5))
array = np.array(array)
colors = ["red", "grey", "green"]
heatmap = sb.heatmap(array, cmap = ["red", "grey", "green"], cbar=False)
#Create dummy handles using scatter
handles = [plt.scatter([], [], marker='s', s=50, color=color) for color in colors]
labels = [-1, 0 , 1]
#Creating the legend using dummy handles
heatmap.figure.legend(handles=handles, labels=labels, loc='center right', frameon=False)
#Adjusting the plot space to the right to make room for the legend
heatmap.figure.subplots_adjust(right=0.8)
plt.show()
On a sidenote:
You can replace your code for the generation of the random array with a numpy function, that does exactly what you want but is way more conventient.
So replace this:
array = []
for x in range(10):
array.append(random.choices([-1,0, 1], k = 5))
array = np.array(array)
With this:
array = np.random.choice((-1, 0, 1), (10, 5))
where the first argument is the choices and the second argument is the shape of the array, so in your case 10 by 5.
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).
The following code generates a matrix plot that every square of it indexed in the middle with a number from 1 to 39:
import numpy as np
from matplotlib import pyplot as plt
a=np.random.uniform(0,1,1600).reshape((40,40))
fig, ax = plt.subplots(1,1)
ax.matshow(a, vmin = 0, vmax = 1, interpolation = 'none')
label_list=np.arange(0,40,5)
label_list=np.append(label_list,39)
ax.set_xticks(label_list)
ax.set_yticks(label_list)
plt.show()
When I want to change the numbers to be between 0 and 1.95 or basically [0,39]*0.05 the labels shrink to the beginning of axes. If I try to use extent in matshow then the labels don't point to the middle of squares! How can I make this float indices to point to the middle of squares?
import numpy as np
from matplotlib import pyplot as plt
a=np.random.uniform(0,1,1600).reshape((40,40))
fig, ax = plt.subplots(1,1)
ax.matshow(a, vmin = 0, vmax = 1, interpolation = 'none')
tick_list = np.append(np.arange(0,40,5), 39)
label_list=map(lambda x: str(0.05*x), tick_list)
ax.set_xticks(tick_list)
ax.set_xticklabels(label_list)
ax.set_yticks(tick_list)
ax.set_yticklabels(label_list)
plt.show()
I have a table which looks like this
I have the highlighted part as a matrix of which I want to do an imshow. I want to have the x-scale of the plot logarithmic, as one can understand by looking at the parameter values in the topmost row. How to do this is matplotlib?
You want to use pcolor, not imshow. Here's an example:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
Z = np.random.random(size=(7,7))
x = 10.0 ** np.arange(-2, 5)
y = 10.0 ** np.arange(-4, 3)
ax.set_yscale('log')
ax.set_xscale('log')
ax.pcolor(x, y, Z)
Which give me:
I'm trying to shade points in a scatter plot based on a set of values (from 0 to 1) picked from one of the already defined color maps, like Blues or Reds. I tried this:
import matplotlib
import matplotlib.pyplot as plt
from numpy import *
from scipy import *
fig = plt.figure()
mymap = plt.get_cmap("Reds")
x = [8.4808517662594909, 11.749082788323497, 5.9075039082855652, 3.6156231827873615, 12.536817102137768, 11.749082788323497, 5.9075039082855652, 3.6156231827873615, 12.536817102137768]
spaced_colors = linspace(0, 1, 10)
print spaced_colors
plt.scatter(x, x,
color=spaced_colors,
cmap=mymap)
# this does not work either
plt.scatter(x, x,
color=spaced_colors,
cmap=plt.get_cmap("gray"))
But it does not work, using either the Reds or gray color map. How can this be done?
edit: if I want to plot each point separately so it can have a separate legend, how can I do it? I tried:
fig = plt.figure()
mymap = plt.get_cmap("Reds")
data = np.random.random([10, 2])
colors = list(linspace(0.1, 1, 5)) + list(linspace(0.1, 1, 5))
print "colors: ", colors
plt.subplot(1, 2, 1)
plt.scatter(data[:, 0], data[:, 1],
c=colors,
cmap=mymap)
plt.subplot(1, 2, 2)
# attempt to plot first five points in five shades of red,
# with a separate legend for each point
for n in range(5):
plt.scatter([data[n, 0]], [data[n, 1]],
c=[colors[n]],
cmap=mymap,
label="point %d" %(n))
plt.legend()
but it fails. I need to make a call to scatter for each point so that it can have a separate label=, but still want each point to have a different shade of the color map as its color.
thanks.
If you really want to do this (what you describe in your edit), you have to "pull" the colors from your colormap (I have commented all changes I made to your code):
import numpy as np
import matplotlib.pyplot as plt
# plt.subplots instead of plt.subplot
# create a figure and two subplots side by side, they share the
# x and the y-axis
fig, axes = plt.subplots(ncols=2, sharey=True, sharex=True)
data = np.random.random([10, 2])
# np.r_ instead of lists
colors = np.r_[np.linspace(0.1, 1, 5), np.linspace(0.1, 1, 5)]
mymap = plt.get_cmap("Reds")
# get the colors from the color map
my_colors = mymap(colors)
# here you give floats as color to scatter and a color map
# scatter "translates" this
axes[0].scatter(data[:, 0], data[:, 1], s=40,
c=colors, edgecolors='None',
cmap=mymap)
for n in range(5):
# here you give a color to scatter
axes[1].scatter(data[n, 0], data[n, 1], s=40,
color=my_colors[n], edgecolors='None',
label="point %d" %(n))
# by default legend would show multiple scatterpoints (as you would normally
# plot multiple points with scatter)
# I reduce the number to one here
plt.legend(scatterpoints=1)
plt.tight_layout()
plt.show()
However, if you only want to plot 10 values and want to name every single one,
you should consider using something different, for instance a bar chart as in this
example. Another opportunity would be to use plt.plot with a custom color cycle, like in this example.
As per the documentation, you want the c keyword argument instead of color. (I agree that this is a bit confusing, but the "c" and "s" terminology is inherited from matlab, in this case.)
E.g.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
x, y, colors = np.random.random((3,10))
fig, ax = plt.subplots()
ax.scatter(x, y, c=colors, s=50, cmap=mpl.cm.Reds)
plt.show()
How about:
import matplotlib.pyplot as plt
import numpy as np
reds = plt.get_cmap("Reds")
x = np.linspace(0, 10, 10)
y = np.log(x)
# color by value given a cmap
plt.subplot(121)
plt.scatter(x, y, c=x, s=100, cmap=reds)
# color by value, and add a legend for each
plt.subplot(122)
norm = plt.normalize()
norm.autoscale(x)
for i, (x_val, y_val) in enumerate(zip(x, y)):
plt.plot(x_val, y_val, 'o', markersize=10,
color=reds(norm(x_val)),
label='Point %s' % i
)
plt.legend(numpoints=1, loc='lower right')
plt.show()
The code should all be fairly self explanatory, but if you want me to go over anything, just shout.