我正在尝试使用此代码段将图例添加到我的情节中:
import matplotlib.pylab as plt
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # left, bottom, width, height (range 0 to 1)
axes.set_xlabel('x (m)')
axes.set_ylabel('y (m)')
for i, representative in enumerate(representatives):
axes.plot([e[0] for e in representative], [e[1] for e in representative], color='b', label='Representatives')
axes.scatter([e[0] for e in intersections], [e[1] for e in intersections], color='r', label='Intersections')
axes.legend()
我最终得到了这个情节
显然,这些项目在图中是重复的。如何更正此错误?
答案 0 :(得分:40)
正如docs所说,虽然很容易错过:
如果label属性为空字符串或以“_”开头,那么这些艺术家 将被忽略。
因此,如果我在循环中绘制类似的线条,并且我只想在图例中使用一个示例行,我通常会执行类似
的操作ax.plot(x, y, label="Representatives" if i == 0 else "")
其中i
是我的循环索引。
单独构建它们并不是很好,但我经常希望标签逻辑尽可能靠近线条图。
(请注意,matplotlib
开发人员自己倾向于使用"_nolegend_"
来明确。)
答案 1 :(得分:7)
这是一种在正常分配标签后删除重复图例条目的方法:
representatives=[[[-100,40],[-50,20],[0,0],[75,-5],[100,5]], #made up some data
[[-60,80],[0,85],[100,90]],
[[-60,15],[-50,90]],
[[-2,-2],[5,95]]]
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # left, bottom, width, height (range 0 to 1)
axes.set_xlabel('x (m)')
axes.set_ylabel('y (m)')
for i, representative in enumerate(representatives):
axes.plot([e[0] for e in representative], [e[1] for e in representative],color='b', label='Representatives')
#make sure only unique labels show up (no repeats)
handles,labels=axes.get_legend_handles_labels() #get existing legend item handles and labels
i=arange(len(labels)) #make an index for later
filter=array([]) #set up a filter (empty for now)
unique_labels=tolist(set(labels)) #find unique labels
for ul in unique_labels: #loop through unique labels
filter=np.append(filter,[i[array(labels)==ul][0]]) #find the first instance of this label and add its index to the filter
handles=[handles[int(f)] for f in filter] #filter out legend items to keep only the first instance of each repeated label
labels=[labels[int(f)] for f in filter]
axes.legend(handles,labels) #draw the legend with the filtered handles and labels lists
以下是结果:
左边是上面脚本的结果。在右侧,图例调用已替换为axes.legend()
。
优点是您可以查看大部分代码并正常分配标签,而不必担心内联循环或if
。你也可以将它构建成一个包围图例或类似内容的包装器。
答案 2 :(得分:2)
这不是错误。 for
循环中的标签正在为您的图例添加len(representatives)-1
个重复标签。如果相反你做了像
for i, representative in enumerate(representatives):
rep, = axes.plot([e[0] for e in representative], [e[1] for e in representative], color='b')
inter = axes.scatter([e[0] for e in intersections], [e[1] for e in intersections], color='r')
axes.legend((rep, inter), ("Representatives", "Intersections"))
编辑:以下代码的格式使用matplotlib legend tutorial上发布的格式。上述代码失败的原因是rep, =
之后缺少逗号。每次迭代rep
都会被覆盖,当用于调用legend
时,只有最后一个代表图存储在rep
中。
fig = plt.figure()
ax = fig.add_subplot(111)
for i, representative in enumerate(representatives):
rep, = ax.plot([e[0] for e in representative], [e[1] for e in representative], color='b')
inter = ax.scatter([e[0] for e in intersections], [e[1] for e in intersections], color='r')
ax.legend((rep, inter), ("Representatives", "Intersections"))
您也可以尝试以您在OP中的方式绘制数据,但使用
制作图例handles, labels = ax.get_legend_handles_labels()
并修改handles
和labels
的内容。
答案 3 :(得分:1)
基于the answer by EL_DON,这是一种常规方法,用于绘制没有重复标签的图例:
def legend_without_duplicate_labels(ax):
handles, labels = ax.get_legend_handles_labels()
unique = [(h, l) for i, (h, l) in enumerate(zip(handles, labels)) if l not in labels[:i]]
ax.legend(*zip(*unique))
用法示例:(open in repl.it
)
fig, ax = plt.subplots()
ax.plot([0,1], [0,1], c="y", label="my lines")
ax.plot([0,1], [0,2], c="y", label="my lines")
legend_without_duplicate_labels(ax)
plt.show()
答案 4 :(得分:0)
根据先前的答案,我使用如下列表解决了类似的问题:
plotted = []
for class_label in classes:
if class_label == class_label:
if label not in plotted:
plt.scatter(x, y, label=class_label)
plotted.append(label)
else:
plt.scatter(x, y)
希望对某人有所帮助:)