【问题标题】:Group by date in pandas in order to plot categorical distributions在熊猫中按日期分组以绘制分类分布
【发布时间】:2016-02-25 03:50:30
【问题描述】:

我正在尝试绘制已按特定日期范围分类的数据。

例如,我有以下数据框:

dates = pd.date_range(start=pd.datetime(2013, 6, 1), periods=50, freq='D')
df = pd.DataFrame(np.random.normal(10, 3, 50), columns=['x'], index=dates)
df[:3]
            x
2013-06-01  9.819422
2013-06-02  3.659629
2013-06-03  14.862231

我想以 3 周为间隔对日期进行分组并绘制数据,这给出了我正在寻找的平均值,

df.resample('3w', how='mean')

            x
2013-06-02  11.424715
2013-06-23  9.443888
2013-07-14  8.572851
2013-08-04  9.873879

但我想保留所有数据,以便在seaborn 中使用箱线图或使用matplotlib 包含标准错误。我完全坚持如何在没有明确定义范围的情况下实现这一点(这对于我正在使用的实际数据帧是不可能的)。在 pandas 中似乎必须有一种相当简单的方法来执行此操作,因此输出将类似于:

            x           week
2013-06-01  9.819422    1
2013-06-02  3.659629    1
2013-06-03  14.862231   1

其中week 是代表分箱数据的分类变量。任何想法将不胜感激。

【问题讨论】:

    标签: python pandas matplotlib seaborn


    【解决方案1】:

    也许你可以使用 TimeGrouper。

    df.groupby(pd.TimeGrouper('3w', how=np.mean)).describe().unstack()
                   x                                                                          
               count       mean       std       min       25%        50%        75%        max
    2013-06-02     2  10.864835  3.794379  8.181803  9.523319  10.864835  12.206350  13.547866
    2013-06-23    21   9.888556  3.452331  3.503944  7.838625   9.739525  12.403285  16.031644
    2013-07-14    21  10.475142  2.687320  6.605619  8.399518  11.209683  11.818895  16.265771
    2013-08-04     6   9.471931  3.196345  5.492205  8.122607   8.502217  10.901065  14.638198
    
    >>> g = df.groupby(pd.TimeGrouper('3w', how=np.mean)).boxplot()
    

    将期间开始日期(作为字符串)添加到原始数据:

    df = pd.DataFrame(np.random.normal(10, 3, 50), columns=['x'], index=dates)
    tg = df.groupby(pd.TimeGrouper('3W', closed='left'))
    df['period'] = None
    for p, idx in tg.indices.iteritems():
        df.ix[idx, 'period'] = p.strftime('%Y-%m-%d')
    
    >>> df.head()
                        x      period
    2013-06-01   7.972202  2013-06-16
    2013-06-02  12.184312  2013-06-16
    2013-06-03   6.884374  2013-06-16
    2013-06-04   8.414091  2013-06-16
    2013-06-05  12.368407  2013-06-16
    

    【讨论】:

    • 这适用于大多数情况,但是,我真的希望能够生成我作为示例提供的数据框,因为我还希望能够计算其他统计数据。
    • 尝试tg = df.groupby(pd.TimeGrouper('3w')) 并使用tg. 和tab 补全来查看可用的方法。请注意 .get_group 以及所有其他可用的统计信息。
    【解决方案2】:

    我会怎么做:

    for idx,w in enumerate(df.groupby(pd.TimeGrouper("3w-SAT"))): # your first day is a saturday
        df.loc[w[0], "week"] = idx+1
    
    # propagate the week number
    df["week"] = df.week.fillna(method="ffill") 
    
    # remove added date by the Timegrouper as your number of date is not a multiple of 3 weeks.
    df.dropna(inplace=1) 
    df.tail()
    
                        x  week
    2013-07-16  15.717111     3
    2013-07-17   9.815201     3
    2013-07-18   9.426426     3
    2013-07-19  12.725350     3
    2013-07-20  16.100748     3
    
    
    # just use seaborn as usual
    sns.boxplot(data=df, x="week", y="x") # plot it
    

    不知道有没有更好的办法直接用Seaborn用TimeGrouper

    HTH

    【讨论】:

    • 谢谢,这是个好建议。在完整数据集上运行此程序时出现错误,我认为是因为存在重复的时间索引,但我并不肯定,我需要进行更多调查。
    • @johnchase,尝试减少您的数据集,并分享它,以便我们重现错误。 (或制作另一个重现错误的假冒产品)
    猜你喜欢
    • 2013-10-26
    • 2020-07-10
    • 1970-01-01
    • 1970-01-01
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 2018-04-01
    相关资源
    最近更新 更多