我有以下数据集:
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'
当我检查lineObjects
:
>>> lineObjects[0].get_label()
['foo', 'bar', 'baz']
>>> lineObjects[1].get_label()
['foo', 'bar', 'baz']
>>> lineObjects[2].get_label()
['foo', 'bar', 'baz']
是否有一种优雅的方法可以使用.plot()
方法分配多个标签?
答案 0 :(得分:43)
您可以遍历线对象列表,因此可以单独指定标签。内置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
传递(假设(numpy)[http://numpy.scipy.org/]之前已导入)时,仍然可以考虑在y数组上不迭代的一步绘图。
在这种情况下,使用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 :(得分:35)
不可能直接相互绘制这两个数组(至少版本为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答案&amp;评论细节。
答案 2 :(得分:28)
我遇到了同样的问题,现在我发现了一个最简单的解决方案!希望对你来说还不算太晚。没有迭代器,只需将结果分配给结构......
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()
看起来像这样:
答案 3 :(得分: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()
答案 4 :(得分:2)
目前最好的解决方案是:
var ans = from i in src
group i by i.Item into ig
let PurchaseQty = ig.Where(i => i.Type == "Purchase").Sum(i => i.Qty)
let SalesQty = ig.Where(i => i.Type == "Sales").Sum(i => i.Qty)
let ReturnQty = ig.Where(i => i.Type == "Return").Sum(i => i.Qty)
select new {
Item = ig.Key,
Qty = PurchaseQty - SalesQty - ReturnQty
};
答案 5 :(得分:1)
我想基于绘制具有两列的矩阵来回答这个问题。
假设你有一个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()
我希望这会有所帮助
答案 6 :(得分:0)
我使用以下内容显示了数据框的标签,而不使用数据框图:
lines_ = plot(df)
legend(lines_, df.columns) # df.columns is a list of labels
答案 7 :(得分: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()
答案 8 :(得分:0)
当我在数组的列中有一组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调用放到一个实用工具中,该实用工具仅打开标签的包装,但是这将需要大量重复才能弄清楚如何解析多个数据集(可能具有不同的列数)并分布在多个参数中,关键字还是其他关键字。