【问题标题】:Plotting legend for 2D numpy array绘制二维 numpy 数组的图例
【发布时间】:2016-05-18 23:49:23
【问题描述】:

我喜欢使用 Numpy 和 Matplotlib 根据某些数字创建图例,但无济于事。所以我开始玩弄一个测试函数来让它正确,然后再将它转移到我的主脚本。

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np

min_xyz = np.random.randint(5, size=(50,1,50))

fig = plt.figure(figsize=(7,7))
ax = fig.add_subplot(111)
ax.set_title('test')
plt.imshow(min_xyz[:,0,:])
ax.set_aspect('equal')

ax.set_xlabel('Distance')
ax.set_ylabel('Depth')
ax.legend()

所以这会创建类似这样的东西

我想创建显示以下内容的图例:

 Mineral 1 = colour_1
 Mineral 2 = colour_2
 Mineral 3 = colour_3
 Mineral 4 = colour_4
 Mineral 5 = colour_5

我尝试使用 ax.legend(),但似乎无法正确处理。有什么想法吗?

编辑:垂直彩条的解决方案

我使用 j08lue 输入的解决方案 - 垂直彩条

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.patches as mpatches

min_xyz = np.random.randint(5, size=(50,1,50))

fig, ax = plt.subplots(figsize = (7,40))
ax.set_title('test')
cax = ax.imshow(min_xyz[:,0,:], cmap = plt.cm.Accent)

"""Handles for min_xyz"""
cbar = plt.colorbar(cax, ticks=[0, 1, 2, 3, 4], 
                    orientation='vertical',
                    fraction=0.045, pad=0.05)
cbar.ax.set_yticklabels(['Mineral 1', 'Mineral 2', 'Mineral 3', 'Mineral 4','Mineral 5'])

ax.set_xlabel('Distance')
ax.set_ylabel('Depth')

编辑:创建自定义图例

我已经放置了 j08lue 建议的解决方案,并设法使第一个图例正确。但是,我相信这与颜色条的规范化有关,以使图例反映正确的颜色。我知道我错过了一些东西,但我不确定我应该寻找什么。非常感谢任何输入。

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.patches as mpatches

min_xyz = np.random.randint(5, size=(50,50))

fig2, ax2 = plt.subplots(figsize = (7,40))
ax = fig.add_subplot(111)
ax2.set_title('test')
cax2 = ax2.imshow(min_xyz, cmap = plt.cm.Accent, vmin=0, vmax=4)
ax2.set_aspect('equal')

"""Handles for min_xyz"""
 my_colors = {
    'Mineral 1' : 0.,
    'Mineral 2' : 1., # It is normalised to 0 to 1
    'Mineral 3' : 2.,
    'Mineral 4' : 3.,
    'Mineral 5' : 4.,
}
patches = [mpatches.Patch(color=cmap(v), label=k) for k,v in sorted(my_colors.items(), key=lambda t: t[0])]
plt.legend(handles=patches, loc=2, bbox_to_anchor=(1.01,1))

ax2.set_xlabel('Distance')
ax2.set_ylabel('Depth')

【问题讨论】:

  • 用彩条解决方案编辑帖子。正在与代理艺术家一起研究可能的解决方案。
  • 太棒了,你搞清楚了。 =) 但是,my_colors 中的值不在 0 和 1 之间。改为使用0, 0.1, 0.2, 0.3, 0.4,它看起来会好很多。或者,更好的是,改用0, 0.25, 0.5, 0.75, 1 来利用颜色图的整个光谱。这就是我将您的数据标准化为 (0,1) 的意思。

标签: python arrays numpy matplotlib legend


【解决方案1】:

代理艺术家

这可以通过proxy artists 完成。文档中的示例:

import matplotlib.patches as mpatches
import matplotlib.pyplot as plt

red_patch = mpatches.Patch(color='red', label='The red data')
plt.legend(handles=[red_patch])

plt.show()

但是您需要弄清楚哪些颜色对应于哪些值。例如

cmap = plt.cm.viridis
my_colors = {
    'Mineral 1' : 0.1,
    'Mineral 2' : 0.2,
    }

patches = [mpatches.Patch(color=cmap(v), label=k) for k,v in my_colors.items()]

plt.legend(handles=patches)

字典中的数字对应于归一化为 [0,1] 的数据,当然,您需要使用相同的 cmap 绘制数据。

替代方案:彩条

或者,您可以添加colorbar(相当于imshow 绘图等中的图例)和place your labels on the ticks

cbar = plt.colorbar(cax, ticks=list(my_colors.values()), orientation='horizontal')
cbar.ax.set_xticklabels(list(my_colors.keys()))

【讨论】:

  • 注意:制作补丁时可能需要对字典进行排序,如果您希望它们按字母顺序排列:sorted(my_colors.items(), key=lambda t: t[0])
  • 感谢您的输入 j08lue,我只能通过使用颜色条来解决问题。但是,我不希望对数据进行规范化(因为数据是整数(0、1、2、3、4)。
  • 您不需要规范化数据。只有 cmap(v) 的值必须介于 0 和 1 之间。
猜你喜欢
  • 1970-01-01
  • 2018-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-17
相关资源
最近更新 更多