停止在图例中重复标签的matplotlib

时间:2012-11-27 16:42:25

标签: matplotlib legend

这是一个非常简单的例子:

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

5 个答案:

答案 0 :(得分:80)

legend将轴句柄和标签列表作为参数,默认为plt.gca().get_legend_handles_labels()。您可以在调用legend时删除重复的标签,例如:

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

答案 1 :(得分:6)

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)

答案 2 :(得分:1)

我不知道这是否可以被考虑"优雅",但您可以让您的标签变量在首次使用后设置为"_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()

Figure with 2 different labels

(答案受https://stackoverflow.com/a/19386045/1878788启发)

答案 3 :(得分:0)

根据回答https://stackoverflow.com/a/13589144/9132798https://stackoverflow.com/a/19386045/9132798 plt.gca().get_legend_handles_labels()[1]给出了一个名称列表,可以在循环绘图(label= name[i] if name[i] not in plt.gca().get_legend_handles_labels()[1] else '')中检查标签是否已经在列表中。 对于给定的示例,此解决方案将如下所示:

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

https://stackoverflow.com/a/13589144/9132798短得多,比https://stackoverflow.com/a/19386045/9132798更灵活,因为它可以单独用于任何类型的循环中的任何绘图函数。 但是,对于许多周期,它可能比https://stackoverflow.com/a/13589144/9132798慢。

答案 4 :(得分:0)

问题-3D阵列

问题:Nov 2012Oct 2013

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

解决方案-字典的唯一性

就我而言,_nolegend_bliDSM)将不起作用,label if i==0也将不起作用。 ecatmur的答案使用get_legend_handles_labels,并用collections.OrderedDict减少图例。 Fons演示了无需导入即可实现的功能。

为回答这些问题,我建议使用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()
相关问题