88

这是一个非常简化的示例:

xvalues = [2,3,4,6]

for x in xvalues:
    plt.axvline(x,color='b',label='xvalues')

plt.legend()

在此处输入图像描述

图例现在将在图例中将“xvalues”显示为蓝线 4 次。有没有比以下更优雅的方法来解决这个问题?

for i,x in enumerate(xvalues):
    if not i:
        plt.axvline(x,color='b',label='xvalues')
    else:
        plt.axvline(x,color='b')

在此处输入图像描述

4

6 回答 6

156

plt.legend作为参数

  1. Artist作为对象的轴手柄列表
  2. 字符串标签列表

这些参数都是可选的,默认为plt.gca().get_legend_handles_labels(). 您可以在调用legend. 这是因为 dicts 不能有重复的键。

例如:

对于 Python 版本 < 3.7

from collections import OrderedDict
import matplotlib.pyplot as plt

handles, labels = plt.gca().get_legend_handles_labels()
by_label = OrderedDict(zip(labels, handles))
plt.legend(by_label.values(), by_label.keys())

对于 Python 版本 > 3.7

从 Python 3.7 开始,字典默认保留输入顺序。因此,不需要OrderedDict形成集合模块。

import matplotlib.pyplot as plt

handles, labels = plt.gca().get_legend_handles_labels()
by_label = dict(zip(labels, handles))
plt.legend(by_label.values(), by_label.keys())

在此处输入图像描述

文档_plt.legend

于 2012-11-27T16:53:49.217 回答
8
handles, labels = ax.get_legend_handles_labels()
handle_list, label_list = [], []
for handle, label in zip(handles, labels):
    if label not in label_list:
        handle_list.append(handle)
        label_list.append(label)
plt.legend(handle_list, label_list)
于 2014-10-24T14:54:02.807 回答
4

我不知道这是否可以被认为是“优雅的”,但是您可以将标签设置为"_nolegend_"第一次使用后设置的变量:

my_label = "xvalues"
xvalues = [2,3,4,6]

for x in xvalues:
    plt.axvline(x, color='b', label=my_label)
    my_label = "_nolegend_"

plt.legend()

如果您必须放置多个标签,则可以使用标签字典对其进行概括:

my_labels = {"x1" : "x1values", "x2" : "x2values"}
x1values = [1, 3, 5]
x2values = [2, 4, 6]

for x in x1values:
    plt.axvline(x, color='b', label=my_labels["x1"])
    my_labels["x1"] = "_nolegend_"
for x in x2values:
    plt.axvline(x, color='r', label=my_labels["x2"])
    my_labels["x2"] = "_nolegend_"

plt.legend()

带有 2 个不同标签的图

(答案灵感来自https://stackoverflow.com/a/19386045/1878788

于 2016-12-19T17:56:00.997 回答
3

问题 - 3D 阵列

问题:2012 年 11 月, 2013 年10 月

import numpy as np
a = np.random.random((2, 100, 4))
b = np.random.random((2, 100, 4))
c = np.random.random((2, 100, 4))

解决方案 - dict 唯一性

对于我的情况_nolegend_bliDSM)不起作用,也不会label if i==0ecatmur的答案使用get_legend_handles_labels并减少了传说collections.OrderedDictFons演示了这在没有导入的情况下是可能的。

根据这些答案,我建议使用dict独特的标签。

# Step-by-step
ax = plt.gca()                      # Get the axes you need
a = ax.get_legend_handles_labels()  # a = [(h1 ... h2) (l1 ... l2)]  non unique
b = {l:h for h,l in zip(*a)}        # b = {l1:h1, l2:h2}             unique
c = [*zip(*b.items())]              # c = [(l1 l2) (h1 h2)]
d = c[::-1]                         # d = [(h1 h2) (l1 l2)]
plt.legend(*d)

或者

plt.legend(*[*zip(*{l:h for h,l in zip(*ax.get_legend_handles_labels())}.items())][::-1])

可能不如Matthew Bourque的解决方案清晰易记。 代码高尔夫欢迎。

例子

import numpy as np
a = np.random.random((2, 100, 4))
b = np.random.random((2, 100, 4))

import matplotlib.pyplot as plt
fig, ax = plt.subplots(1)
ax.plot(*a, 'C0', label='a')
ax.plot(*b, 'C1', label='b')

ax.legend(*[*zip(*{l:h for h,l in zip(*ax.get_legend_handles_labels())}.items())][::-1])
# ax.legend()   # Old,  ^ New

plt.show()
于 2019-08-21T22:50:26.747 回答
2

Based on answer https://stackoverflow.com/a/13589144/9132798 and https://stackoverflow.com/a/19386045/9132798 plt.gca().get_legend_handles_labels()[1] gives a list of names, it is possible to check if the label is already in the list while in the loop plotting (label= name[i] if name[i] not in plt.gca().get_legend_handles_labels()[1] else ''). For the given example this solution would look like:

import matplotlib.pyplot as plt

xvalues = [2,3,4,6]

for x in xvalues:
    plt.axvline(x,color='b',\
    label= 'xvalues' if 'xvalues' \
            not in plt.gca().get_legend_handles_labels()[1] else '')

plt.legend()

Which is much shorter than https://stackoverflow.com/a/13589144/9132798 and more flexible than https://stackoverflow.com/a/19386045/9132798 as it could be use for any kind of loop any plot function in the loop individually. However, for many cycles it probably slower than https://stackoverflow.com/a/13589144/9132798.

于 2017-12-23T02:19:12.237 回答
1

这些代码片段对我个人不起作用。我正在用两种不同的颜色绘制两个不同的组。当我只想看到每种颜色一个时,图例将显示两个红色标记和两个蓝色标记。我将粘贴对我有用的简化版本:

导入语句

import matplotlib.pyplot as plt

from matplotlib.legend_handler import HandlerLine2D

绘制数据

points_grp, = plt.plot(x[grp_idx], y[grp_idx], color=c.c[1], marker=m, ms=4, lw=0, label=leglab[1])        
points_ctrl, = plt.plot(x[ctrl_idx], y[ctrl_idx], color=c.c[0], marker=m, ms=4, lw=0, label=leglab[0])

添加图例

points_dict = {points_grp: HandlerLine2D(numpoints=1),points_ctrl: HandlerLine2D(numpoints=1)}
leg = ax.legend(fontsize=12, loc='upper left', bbox_to_anchor=(1, 1.03),handler_map=points_dict)
于 2015-12-21T00:29:13.273 回答