【问题标题】:End pandas Grouper on max date in column在列中的最大日期结束 pandas Grouper
【发布时间】:2021-03-01 16:09:03
【问题描述】:

最小可重现示例

import numpy as np
import pandas as pd

np.random.seed(0)
dates = pd.date_range(start='1/1/2021', end='3/15/2021')
df = pd.DataFrame({'date': np.random.choice(dates, 1000), 
                   'label': np.random.choice(['a', 'b', 'c'], 1000)})

结果

    date    label
0   2021-02-14  a
1   2021-02-17  c
2   2021-03-06  a
3   2021-03-09  c
4   2021-03-09  b
... ... ...
995 2021-03-06  c
996 2021-01-14  b
997 2021-01-02  a
998 2021-01-03  c
999 2021-03-08  b

我试图从最后观察到的日期开始每 4 周对日期列进行分组(在这种情况下,df['date'].max() 给出'3/15/2021',所以我希望按日期和标签分组时的最后日期为@987654326 @ 以及对其他日期进行相应调整(3/15 前 28 天、3/15 前 56 天等)。

但是,我无法使用 pd.Grouper 执行此操作。 According to the docspd.Grouper 采用 origin 参数来调整分组,但没有基于结束日期的选项。

有没有办法以类似于以下方式使用pd.Grouper

df.groupby([pd.Grouper(key='date', freq='28d', label='right'), 'label'])['label'].count()
date        label
2021-01-29  a        114
            b        135
            c        134
2021-02-26  a        125
            b        133
            c        123
2021-03-26  a         83
            b         81
            c         72
Name: label, dtype: int64

而是将最后一个按日期分组的 end 设置为 3/15(并且最后一个组包含自 3/15 以来 28 天的所有数据)?

【问题讨论】:

    标签: python pandas date pandas-groupby


    【解决方案1】:

    我们可以尝试用 div 创建日期计数

    df_sub = df.assign(v = ((df.date-df.date.max()).dt.days.sub(1)//28))
    s = df_sub.groupby(['v','label']).agg({'label':'count'})
    s = s.join(df_sub.groupby('v').date.max())
    Out[41]: 
              label       date
    v  label                  
    -3 a         76 2021-01-18
       b         87 2021-01-18
       c         91 2021-01-18
    -2 a        120 2021-02-15
       b        138 2021-02-15
       c        126 2021-02-15
    -1 a        126 2021-03-15
       b        124 2021-03-15
       c        112 2021-03-15
    

    【讨论】:

    • 我也想过这个问题,但是如果2021-02-15 没有出现在数据中,最后一个date.max() 上的连接可能不起作用。
    【解决方案2】:

    显然pd.Grouper 不支持负频。我会决定按Timedelta分组:

    out = (df.groupby((max_date-df['date'])//pd.Timedelta('28d'))
       ['label'].value_counts()
    )
    
    # relabel the index
    out.index = pd.MultiIndex.from_tuples([
        (max_date - pd.to_timedelta(x*28, unit='D'),y) for x,y in out.index
    ], names=['date','label'])
    

    输出:

    date        label
    2021-03-15  a        126
                b        124
                c        112
    2021-02-15  b        138
                c        126
                a        120
    2021-01-18  c         91
                b         87
                a         76
    Name: label, dtype: int64
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-05-19
      • 2020-06-20
      • 1970-01-01
      • 2019-11-21
      • 2014-09-21
      • 2016-02-28
      • 2017-11-02
      • 2016-06-01
      相关资源
      最近更新 更多