使用 Grouper 按日期时间频率对行进行分组并绘制另一列的计数(使用复制代码)

use Grouper to group rows by datetime frequency and plot count of another column (with reproduction code)

为简单起见,假设我有一个数据框,排列如下:

import numpy as np
import pandas as pd
def random_dates(start, end, n, unit='D', seed=None):
    if not seed:  
        np.random.seed(0)

    ndays = (end - start).days + 1
    return pd.to_timedelta(np.random.rand(n) * ndays, unit=unit) + start
np.random.seed(0)
start = pd.to_datetime('2015-01-01')
end = pd.to_datetime('2018-01-01')
date = random_dates(start, end, 1000)
#%%
gender = np.random.randint(0,2,(1000,))
DF = pd.DataFrame({'datetime_of_call':date,'gender_of_caller':gender})

我想绘制男性和女性来电者在某条线上的分布,作为 year/month/hour ON TOTAL 的函数(另外,我们现在可以说只是一个月)

例如,我想直观地看到 不论年份 ,特别是在 1 月份,女性来电者的比例很高。另一个例子是,如果我希望频率为每小时,那么我想知道 male/female 在所有年份中的分布情况,仅按小时计算。

我用grouper按月分组:

DF.groupby(pd.Grouper(key='datetime_of_call',freq='M'))

现在不确定如何继续,我尝试了以下方法:

pd.crosstab(DF.groupby(pd.Grouper(key='datetime_of_call',freq='M')),DF.gender_of_caller).plot.bar(stacked=True)

但出现错误

ValueError: Shape of passed values is (37, 2), indices imply (1000, 2)

我想你可以用 groupbyto_period

来实现
gb = DF.groupby(['gender_of_caller', DF.datetime_of_call.dt.to_period('M')]).size()
df = gb.unstack()

为您提供如下数据框:

然后你可以用

进行转置
df = df.T

然后您可以将其绘制为条形图或其他内容:

df.plot(kind='bar')

编辑:如果您希望分组依据是月份而不考虑年份,您可以将 groupby 行更改为:

gb = DF.groupby(['gender_of_caller', DF.datetime_of_call.dt.month]).size()

现在最终图表将如下所示: