71

我有以下数据集:

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)

.legend()但是,我想用这个命令标记 3 个 y 数据集,这会在调用时引发错误:

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'

当我检查lineObjects

>>> lineObjects[0].get_label()
['foo', 'bar', 'baz']
>>> lineObjects[1].get_label()
['foo', 'bar', 'baz']
>>> lineObjects[2].get_label()
['foo', 'bar', 'baz']

问题

有没有一种优雅的方法可以通过使用该.plot()方法来分配多个标签?

4

9 回答 9

63

您可以遍历您的线对象列表,因此标签是单独分配的。带有内置 pythoniter函数的示例:

lineObjects = plt.plot(x, y)
plt.legend(iter(lineObjects), ('foo', 'bar', 'baz'))`

编辑:更新到 matplotlib 1.1.1 后,看起来plt.plot(x, y)y 作为列表列表(由问题作者提供)不再起作用。numpy.array在将 y 传递为(假设 (numpy)[http://numpy.scipy.org/] 之前已导入)之后,仍然可以考虑在不迭代 y 数组的情况下绘制一步。

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

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

于 2012-07-14T17:59:09.403 回答
47

无法直接将这两个数组相互绘制(至少版本 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 答案和评论。

于 2012-07-15T15:54:13.707 回答
38

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

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

看起来像这样: 在此处输入图像描述

于 2012-11-17T14:19:57.543 回答
9

目前最好的解决方案是:

lineObjects = plt.plot(x, y)  # y describes 3 lines
plt.legend(['foo', 'bar', 'baz'])
于 2020-05-28T22:07:16.207 回答
4

您可以在绘制曲线时给出标签

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

在此处输入图像描述

于 2012-07-14T13:15:14.070 回答
4

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

我希望这有帮助

于 2017-11-09T12:36:09.747 回答
2

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

不幸的是,plt.setp在这里没有帮助。在较新版本的 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,而不必在代码中查看循环。另一种方法是将整个调用 plot 放入一个只解包标签的实用程序中,但这需要大量重复才能弄清楚如何解析多个数据集,可能具有不同数量的列,并分布在多个参数中,关键字或其他。

于 2020-11-11T03:23:55.843 回答
1

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

lines_ = plot(df)
legend(lines_, df.columns) # df.columns is a list of labels
于 2020-05-25T09:04:18.943 回答
0

如果您使用的是 DataFrame,您还可以遍历要绘制的数据的列:

# 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()
于 2020-06-05T13:35:51.830 回答