首页 > 解决方案 > 使用 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'

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

或者是否有更好的方法来实现这一目标?

谢谢。

标签: pandasmatplotliblinegraph

解决方案


你非常亲近。正如第一个错误所示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')

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


推荐阅读