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

19

我正在使用 matplotlib

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

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

enter image description here

我所能想到的是,给矩阵中的每个元素添加标签,然后尝试使用 legend(),看看它是否起作用,但如何为元素添加标签呢,例如值?

在我的情况下,原始数据如下:

1,2,3,3,4
2,3,4,4,5
1,1,1,2,2
例如,1代表“草”,2代表“沙子”,3代表“山”......等等。 imshow()在我的情况下完美运行,但没有图例。
我的问题是:
1.是否有一个函数可以自动添加图例,例如,在我的情况下,我只需要这样做:someFunction('grass','sand',...) 2.如果没有,如何为矩阵中的每个值添加标签。 例如,将矩阵中所有的1标记为“草”,将所有的2标记为“沙子”......等等。
谢谢!
编辑: 感谢@dnalow,这真的很聪明。 但是,我仍然想知道是否有任何正式的解决方案。
4个回答

50

我在这里引用一个类似问题的解决方案,以防某人仍然感兴趣:

我认为只有矩阵中没有太多值时,才有必要为所有值设置图例。因此,假设您的矩阵中有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()

在此输入图片描述


这正是我一直在寻找的。感谢您发布这个答案,即使它不是主要问题的答案。 - Chinmay K

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

这段文本的意思是:

这将给你以下内容 random noise

您可以查看 matplotlib 文档中有关文本的更多详细信息 matplotlib 文本示例


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

以下是结果展示

这个分辨率看起来不太好,但它可以工作。我也在寻找其他方法。


3
我猜您需要伪造图例,因为它需要一行来创建图例。
您可以使用以下方法:
```html

我猜您需要伪造图例,因为它需要一行来创建图例。

您可以尝试以下内容:

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

当然,这还不够令人满意。但或许你可以在此基础上构建一些东西。
[编辑:添加缺失的括号]

聪明!我会试试看的!谢谢! - rankthefirst
在那里,您可以找到更适当的解决方案,使用离散的色条和更正的标签。这不是您最初要求的,但可能是一个很好的替代方案。 - dnalow
非常感谢!那是高级的色条,但你的很适合我的情况。它们两个在未来都会很有用,再次感谢~ - rankthefirst

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接