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).

enter image description here

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.

+3


source to share


4 answers


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]

+3


source


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()

      

enter image description here

+8


source


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()

      

which gives you the following random noise

You can check matplotlib documentation on text for more details matplotlib text examples

+5


source


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()

      

show result below

This resolution doesn't sound very good, but it might work. I am also looking for other methods.

0


source







All Articles