使用 python matplotlib 创建多线图

Using python matplotlib to create multi line graph

我想创建一个折线图,其中 y 轴有多条线,用于在我的数据框列中找到的每个唯一条目。

我的数据框看起来像这样 –

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 轴将为每个命令条目(在本例中为开始、保持和释放)单独一行。

我尝试使用 groupby 然后执行这个 –

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'

我还尝试创建一个枢轴 table 并从那里构建图表,如下所示 -

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

但是 returns 错误 - AttributeError: 'DataFrame' object has no attribute 'command'

我不确定我的方法是否遗漏了什么?

或者是否有更好的实现方法?

谢谢。

你们非常亲密。正如第一个错误所示 df.groupby(['command', 'date']).size() returns 一个带有多索引的系列。如果您想使用它,可以使用 .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')

所有这些解决方案都产生相同的输出,但在美学上存在一些细微差异。