How to add legend to imshow () in matplotlib
I use matplotlib
In plot()
or bar()
we can easily put a legend if we add labels to them. but what if it's contourf()
orimshow()
I know there is colorbar()
one that can represent a range of colors, but it fails. I want a legend like this that has names (labels).
For what I can think of add labels to each element in the matrix, then try legend () to see if it works, but how to add a label to the element, like the value
in my case, the original data looks like this:
1,2,3,3,4 2,3,4,4,5 1,1,1,2,2
for example, 1 represents "grass", 2 represents "sand", 3 represents "hill" ... and so on. imshow () works fine with my case, but no legend.
my question is:
-
Is there a function that can automatically add a legend, for example, in my case, I just need to do it like this: someFunction ("grass", "sand", ...)
-
If it doesn't, how do I add labels to each value in the matrix. For example, name all 1s in the matrix grass, put all 2s in the sand matrix, and so on.
Thank!
Edit
Thanks to @dnalow, he's really smart. However, I'm still wondering if there is any formal solution.
source to share
I think you should fake your legend as it requires a string to create the legend.
You can do something like this:
import pylab as pl
mycmap = pl.cm.jet # for example
for entry in pl.unique(raw_data):
mycolor = mycmap(entry*255/(max(raw_data) - min(raw_data)))
pl.plot(0, 0, "-", c=mycolor, label=mynames[entry])
pl.imshow(raw_data)
pl.legend()
Because of this, it is still not very pleasant. But maybe you can do something about it.
[edit: missing parenthesis added]
source to share
I am quoting a solution to a similar question here in case anyone is still interested:
I suppose that it makes sense to put a legend for all values ββin the matrix if there are not so many of them. So let's say you have 8 different values ββin your matrix. Then we can create a proxy artist of the corresponding color for each one and put them in a legend like this
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import numpy as np
# create some data
data = np.random.randint(0, 8, (5,5))
# get the unique values from data
# i.e. a sorted list of all values in data
values = np.unique(data.ravel())
plt.figure(figsize=(8,4))
im = plt.imshow(data, interpolation='none')
# get the colors of the values, according to the
# colormap used by imshow
colors = [ im.cmap(im.norm(value)) for value in values]
# create a patch (proxy artist) for every color
patches = [ mpatches.Patch(color=colors[i], label="Level {l}".format(l=values[i]) ) for i in range(len(values)) ]
# put those patched as legend-handles into the legend
plt.legend(handles=patches, bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0. )
plt.grid(True)
plt.show()
source to share
You can use matplotlib.pylab.text
to add text to your plot and set it up like a legend
For example:
import numpy as np
import matplotlib.cm as cm
import matplotlib.pylab as plt
raw_data = np.random.random((100, 100))
fig, ax = plt.subplots(1)
ax.imshow(raw_data, interpolation='nearest', cmap=cm.gray)
ax.text(5, 5, 'your legend', bbox={'facecolor': 'white', 'pad': 10})
plt.show()
You can check matplotlib documentation on text for more details matplotlib text examples
source to share
I am just working on the same project to draw a land use map like your problem. Here is my solution following the above answers.
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import numpy as np
##arrayLucc is the array of land use types
arrayLucc = np.random.randint(1,4,(5,5))
## first you need to define your color map and value name as a dic
t = 1 ## alpha value
cmap = {1:[0.1,0.1,1.0,t],2:[1.0,0.1,0.1,t],3:[1.0,0.5,0.1,t]}
labels = {1:'agricultural land',2:'forest land',3:'grassland'}
arrayShow = np.array([[cmap[i] for i in j] for j in arrayLucc])
## create patches as legend
patches =[mpatches.Patch(color=cmap[i],label=labels[i]) for i in cmap]
plt.imshow(arrayShow)
plt.legend(handles=patches, loc=4, borderaxespad=0.)
plt.show()
This resolution doesn't sound very good, but it might work. I am also looking for other methods.
source to share