如何在matplotlib的imshow()中添加图例

20 投票
4 回答
83319 浏览
提问于 2025-04-18 18:25

我正在使用 matplotlib

plot()bar() 中,我们可以很容易地添加图例,只要给它们加上标签。但是如果是 contourf()imshow() 呢?

我知道有一个 colorbar() 可以显示颜色范围,但这并不能满足我的需求。我想要的是一个带有名称(标签)的图例。

在这里输入图片描述

我想到的办法是给矩阵中的每个元素添加标签,然后尝试使用 legend() 来看看是否有效,但怎么给元素添加标签,比如一个值呢?

在我的情况下,原始数据是这样的:

1,2,3,3,4
2,3,4,4,5
1,1,1,2,2

例如,1 代表 '草地',2 代表 '沙子',3 代表 '小山'……依此类推。

imshow() 在我的情况下运行得很好,但没有图例。

我的问题是:

  1. 有没有什么函数可以自动添加图例?比如在我的情况下,我只需要这样做:someFunction('草地','沙子',...)

  2. 如果没有,怎么给矩阵中的每个值添加标签?例如,把矩阵中的所有 1 标记为 '草地',把所有 2 标记为 '沙子'……依此类推。

谢谢!

编辑

感谢 @dnalow,真聪明。不过,我还是想知道有没有什么正式的解决方案。

4 个回答

8

我正在做一个和你一样的项目,目的是绘制一张土地利用地图。这里是我根据上面的回答找到的解决方案。

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

结果如下

这个结果看起来不是很好,但它是可以用的。我也在寻找其他的方法。

9

你可以使用 matplotlib.pylab.text 这个功能来在你的图表上添加文字,并且可以把它调整得像图例一样好看。

比如说:

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

这样做会得到下面这个效果 随机噪声

如果想了解更多关于文字的使用,可以查看 matplotlib 的文档,这里有一些 matplotlib 文字示例

52

我在这里引用了一个解决方案,针对一个类似的问题,以防还有人感兴趣:

我认为在矩阵中为所有值添加图例只有在值不太多的情况下才有意义。假设你的矩阵中有8个不同的值。我们可以为每个值创建一个对应颜色的代理图形,然后把它们放进图例里,像这样:

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

3

我想你得自己做个假的图例,因为创建图例需要一条线。

你可以试试这样做:

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

当然,这样做还不太完美。不过也许你可以在这个基础上继续改进。

[编辑:添加了缺失的括号]

撰写回答