如何在matplotlib中一次指定多个标签?

如何在matplotlib中一次指定多个标签?,matplotlib,label,legend,Matplotlib,Label,Legend,我有以下数据集: x = [0, 1, 2, 3, 4] y = [ [0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [9, 8, 7, 6, 5] ] 现在,我用以下方法绘制它: import matplotlib.pyplot as plt plt.plot(x, y) 但是,我想使用此命令标记3个y数据集,这会在调用.legend()时引发错误: lineObjects = plt.plot(x, y, label=['foo', 'bar'

我有以下数据集:

x = [0, 1, 2, 3, 4]
y = [ [0, 1, 2, 3, 4],
      [5, 6, 7, 8, 9],
      [9, 8, 7, 6, 5] ]
现在,我用以下方法绘制它:

import matplotlib.pyplot as plt
plt.plot(x, y)
但是,我想使用此命令标记3个y数据集,这会在调用
.legend()
时引发错误:

lineObjects = plt.plot(x, y, label=['foo', 'bar', 'baz'])
plt.legend()

File "./plot_nmos.py", line 33, in <module>
  plt.legend()
...
AttributeError: 'list' object has no attribute 'startswith'
问题:
仅使用
.plot()
方法是否有一种优雅的方法来指定多个标签?

您可以在绘制曲线时指定标签

import pylab as plt

x = [0, 1, 2, 3, 4]
y = [ [0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [9, 8, 7, 6, 5] ]
labels=['foo', 'bar', 'baz']
colors=['r','g','b']

# loop over data, labels and colors
for i in range(len(y)):
    plt.plot(x,y[i],'o-',color=colors[i],label=labels[i])

plt.legend()
plt.show()

您可以在“线对象”列表上迭代,因此标签是单独指定的。内置python
iter
函数的示例:

lineObjects = plt.plot(x, y)
plt.legend(iter(lineObjects), ('foo', 'bar', 'baz'))`
编辑:更新到matplotlib 1.1.1后,它看起来像是
plt.plot(x,y)
,其中y是列表列表列表(由问题作者提供),不再工作。在将y作为
numpy.array
传递后,仍然可以考虑在y阵列上不进行迭代的一步绘图(假设(numpy)[http://numpy.scipy.org/]如以前导入的)

在这种情况下,使用
plt.plot(x,y)
(如果2D y数组中的数据排列为列[轴1])或
plt.plot(x,y.transpose())
(如果2D y数组中的数据排列为行[轴0])


编辑2:正如@pelson所指出的那样(见下面的评论),
iter
功能是不必要的,一个简单的
plt.legend(lineObjects,('foo','bar','baz'))
可以完美地工作

不可能直接将这两个数组相互绘制(至少版本为1.1.1),因此,您必须在y数组上循环。我的建议是,同时在标签上循环:

import matplotlib.pyplot as plt

x = [0, 1, 2, 3, 4]
y = [ [0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [9, 8, 7, 6, 5] ]
labels = ['foo', 'bar', 'baz']

for y_arr, label in zip(y, labels):
    plt.plot(x, y_arr, label=label)

plt.legend()
plt.show()

编辑:@gcalmettes指出,作为numpy数组,可以同时绘制所有线条(通过转置它们)。有关详细信息,请参阅@gcalmettes答案和评论。

我遇到了同样的问题,现在我找到了一个最简单的解决方案!希望这对你来说还不算太晚。没有迭代器,只需将结果分配给结构

from numpy import *
from matplotlib.pyplot import *
from numpy.random import *

a = rand(4,4)
a
>>> array([[ 0.33562406,  0.96967617,  0.69730654,  0.46542408],
   [ 0.85707323,  0.37398595,  0.82455736,  0.72127002],
   [ 0.19530943,  0.4376796 ,  0.62653007,  0.77490795],
   [ 0.97362944,  0.42720348,  0.45379479,  0.75714877]])

[b,c,d,e] = plot(a)
legend([b,c,d,e], ["b","c","d","e"], loc=1)
show()
看起来像这样:

如果是numpy矩阵图,则为每列一次指定多个图例 我想在绘制一个有两列的矩阵的基础上回答这个问题

假设您有一个2列矩阵
Ret

然后可以使用此代码一次分配多个标签

import pandas as pd, numpy as np, matplotlib.pyplot as plt
pd.DataFrame(Ret).plot()

plt.xlabel('time')
plt.ylabel('Return')
plt.legend(['Bond Ret','Equity Ret'], loc=0)
plt.show()

我希望这会有所帮助

我使用以下内容来显示数据帧的标签,而不使用数据帧绘图:

lines\uz=绘图(df)
图例(行、df.columns)#df.columns是标签列表

目前最好的解决方案是:

lineObjects=plt.plot(x,y)#y描述了3条线
plt.图例(['foo','bar','baz'])

如果您使用的是数据帧,还可以迭代要绘制的数据列:

# Plot figure
fig, ax = plt.subplots(figsize=(5,5))
# Data
data = data
# Plot
for i in data.columns:
    _ = ax.plot(data[i], label=i)
    _ = ax.legend() 
plt.show()

当我在数组的列中有一组
x
值和多个
y
值时,这个问题经常出现。我真的不想在循环中绘制数据,而且多次调用
ax.legend
/
plt.legend
并不是一个真正的选项,因为我想绘制其他内容,通常是以同样恼人的格式

不幸的是,这在这里没有帮助。在更新版本的matplotlib中,它只是将整个列表/元组转换为字符串,并将整个内容作为标签分配给所有行

因此,我创建了一个实用函数,将对
ax.plot
/
plt.plot
的调用包装到:

def set_labels(artists, labels):
    for artist, label in zip(artists, labels):
        artist.set_label(label)
你可以这样称呼它

x = np.arange(5)
y = np.random.ranint(10, size=(5, 3))

fig, ax = plt.subplots()
set_labels(ax.plot(x, y), 'ABC')

这样,您就可以将所有正常的艺术家参数指定为
绘图
,而不必查看代码中的循环。另一种方法是将对plot的整个调用放入一个只解压缩标签的实用程序中,但这需要大量的重复,以确定如何解析多个数据集,可能具有不同的列数,并分布在多个参数、关键字或其他方面。

,直接迭代y列表,同时压缩其他列表可能更具python风格(参见我的答案)。如果您确实必须这样做,那么与其使用范围(len(…),不如使用枚举(…)。不过你还是得到了+1:-)谢谢你指出这一点。在这种情况下,izip、zip或enumerate更有意义。这对用户不起作用(如果没有迭代步骤,则无法同时绘制提供的x和y)。即使打印成功,假设lineObjects是一个列表(或元组等),iter函数也将是不必要的。@pelson的确,它看起来不适用于新的matplotlib版本。但是,如果x和y是
numpy数组
,您仍然可以使用
plot(x,y.transpose())
一步绘制它们。在这种情况下,iter函数的语法仍然有效。你是对的,我不知道一个简单的转置就能解决这个问题。(numpy数组可以通过以下方式与.T进行转换,即
y.T
)。然而,我仍然坚持你的iter功能在这里是不必要的(尽管它显然仍然有效)。@pelson你是对的,一个简单的
图例(lineObjects,('foo','bar','baz'))
非常有效。我不知道为什么我在这里添加了
iter
函数。。。谢谢
x = np.arange(5)
y = np.random.ranint(10, size=(5, 3))

fig, ax = plt.subplots()
set_labels(ax.plot(x, y), 'ABC')