pandas - 使用 python matplotlib 创建多线图
问题描述
我正在寻找一个折线图,其中 y 轴对于我的数据框列中找到的每个唯一条目都有多条线。
我的数据框看起来像这样 -</p>
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame({'command': ['start', 'start', 'hold',
'release', 'hold', 'start',
'hold', 'hold', 'hold'],
'name': ['fred', 'wilma', 'barney',
'fred', 'barney', 'betty',
'pebbles', 'dino', 'wilma'],
'date': ['2020-05', '2020-05', '2020-05',
'2020-06', '2020-06', '2020-06',
'2020-07', '2020-07', '2020-07']})
我正在尝试创建一个以 X 轴为日期的折线图,并且 y 轴将为每个命令条目(在此示例中为 start、hold 和 release)创建一条单独的线。
我尝试使用 groupby 然后执行这个 -</p>
dfg = df.groupby(['command', 'date']).size()
for i in dfg.command.unique():
x = dfg[dfg.command==i]['date']
y = dfg[dfg.command==i]['size']
plt.plot(x, y)
plt.show()
但是我收到此错误 - AttributeError: 'Series' object has no attribute 'command'
我也尝试过创建一个数据透视表并从那里构建图表,如下所示 -
df_pv = pd.pivot_table(df, index=['command', 'date'],
values='name',
aggfunc='count')
df_pv.rename(columns={'name': 'count'}, inplace=True)
for i in df_pv.command.unique():
x = df_pv[df_pv.command==i]['date']
y = df_pv[df_pv.command==i]['count']
plt.plot(x, y)
plt.show()
但是它返回错误 - AttributeError: 'DataFrame' object has no attribute 'command'
我不确定我的方法是否遗漏了什么?
或者是否有更好的方法来实现这一目标?
谢谢。
解决方案
你非常亲近。正如第一个错误所示df.groupby(['command', 'date']).size()
,返回一个带有多索引的系列。如果要使用它,可以使用将其转换为数据框.reset_index()
dfg = df.groupby(['command', 'date']).size().reset_index()
fig,ax = plt.subplots()
for com in dfg['command'].unique():
ax.plot(dfg.loc[dfg['command']==com,'date'],dfg.loc[dfg['command']==com,0],'o-', label=com)
ax.legend()
请注意,您也可以直接使用 MultiIndex(尽管我通常觉得它更麻烦)。您可以使用以下方法迭代特定级别的多索引groupby(level=)
并访问给定级别的内容MultiIndex.get_level_values()
:
dfg = df.groupby(['command', 'date']).size()
fig,ax = plt.subplots()
for com,subdf in dfg.groupby(level=0):
ax.plot(subdf.index.get_level_values(level=1),subdf.values,'o-', label=com)
ax.legend()
最后,如果您想省去自己编写循环的麻烦,您可以使用seaborn
,这对于这种绘图非常容易使用(尽管您需要像在第一个解决方案中一样转换您的数据框)
dfg = df.groupby(['command', 'date']).size().reset_index()
plt.figure()
sns.lineplot(data=dfg, x='date', y=0, hue='command', marker='o')
如果您想真正花哨,您可以自己放弃转换原始数据框,并seaborn.lineplot()
通过指示它如何聚合每个日期的值来完成它:
sns.lineplot(data=df, x='date', y=0, hue='command', estimator=pd.value_counts, marker='o')
所有这些解决方案都产生相同的输出,但存在一些细微的美学差异。
推荐阅读
- suitescript2.0 - SuiteScript2.0 - 将机会转换为销售订单未正确设置送货地址
- xpath - Xquery如何检查具有属性的元素的值
- javascript - HTMLElement 属性返回未定义——Angular
- python - Python中具有指数(N和P)的数字总和
- google-apps-script - Google 表格列表文本
- c# - 计算本周 SQLite 数据库中的行数
- javascript - 如何重新为多个图像创建模态?
- angular - Angular页面,XPath找不到文本
- kubernetes - 使用 RBAC 为上游和下游配置 Istio 入口网关
- html - 如何更改活动导航链接的背景颜色?