使用matplotlib的堆积条形图

时间:2019-02-23 23:53:13

标签: python-3.x matplotlib pandas-groupby

我有一个从WhatsApp中提取的数据框,其中包含列:日期和时间,消息,名称,消息_len。 Date&Time是一个DateTime对象,表示何时发送消息,msg是实际消息,name是发送消息的人,msg_len是消息的实际长度。信息。 我正在尝试使用此数据框构建堆叠的条形图:在X轴上是日期(例如2019-02),在y轴上是该月发送的平均长度或消息数,每个条形是按每个人划分。到目前为止,我的功能如下:

def BarPlotMonth(Data):
    """
    This function plots a barplot for the number of messages sent for each month and the mean length of the messages for each month
    """

    fig,axes = plt.subplots(2,1,
            figsize=(18,10),
            sharex = True)


    GroupedByMonth = Data.groupby(Data['Date&Time'].dt.strftime('%Y-%m'))['msg_len']

    Mean = GroupedByMonth.mean()
    Count = GroupedByMonth.count()
    Std = GroupedByMonth.std()

    axes[0].bar(Count.index, Count, color = 'lightblue')
    axes[0].set_title('Number of text per month')
    axes[0].set_ylabel('Count')

    axes[1].bar(Mean.index, Mean, color = 'lightblue', yerr = Std)
    axes[1].set_title('Mean lenght of a message per month')
    axes[1].set_ylabel('Mean lenght')
    axes[1].set_xlabel('Year-Month')

    plt.xticks(rotation=45)
    axes[1].legend()

    plt.savefig('WhatsApp_conversations.png')
    plt.show()

但是我不能分开每个小节。我该怎么解决?

1 个答案:

答案 0 :(得分:1)

您将需要稍微重组DataFrame才能使用df.plot(kind='bar', stacked=True)

group_by_month_per_user = df.groupby(
    [
        df['Date&Time'].dt.strftime('%Y-%m'),
        'name'
    ]   
).mean().unstack()

group_by_month_per_user

这将产生具有以下结构的表。

             msg_len                                 
name           alice        bob   giuseppe     martin
Date&Time                                            
2019-01    48.870968  42.315789  56.391304  49.586207
2019-02    51.099174  48.777778  56.173913  51.895652
2019-03    52.336364  49.626168  47.021898  46.626263

请注意,这些列是在所有列上带有msg_len的多重索引,我们需要删除它以使图例保持整洁(可以简单地选择整个列)。然后可以将所得的DataFrame传递给.plot

group_by_month_per_user['msg_len'].plot(kind='bar', stacked=True, legend=['name'])

这将产生以下图。

output showing stacked bar for SMS length

以下代码用于生成随机数据集。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
from random import randint, choice
import string

ts = datetime.now()
data = []
names = ['bob', 'alice', 'martin', 'giuseppe']

for n in range(1000):
    msg_len = randint(0, 100)
    row = [
        ts - timedelta(days=randint(-30,30)),
        ''.join(random.choice(string.ascii_lowercase) for _ in range(msg_len)),
        choice(names),
        msg_len
    ]

    data.append(row)

df = pd.DataFrame(data, columns = ['Date&Time', 'msg', 'name', 'msg_len'])