【问题标题】:Grouping by date range with pandas使用熊猫按日期范围分组
【发布时间】:2018-04-01 00:44:31
【问题描述】:

我希望按两列分组:user_id 和 date;但是,如果日期足够接近,我希望能够将这两个条目视为同一组的一部分并相应地分组。日期是 m-d-y

user_id     date       val
1           1-1-17     1
2           1-1-17     1
3           1-1-17     1
1           1-1-17     1
1           1-2-17     1
2           1-2-17     1
2           1-10-17    1
3           2-1-17     1

分组将按 user_id 和日期 +/- 3 天进行分组。所以通过求和 val 的组看起来像:

user_id     date       sum(val)
1           1-2-17     3
2           1-2-17     2
2           1-10-17    1
3           1-1-17     1
3           2-1-17     1

有人能想到这可以(某种程度上)轻松完成吗?我知道这有一些问题的方面。例如,如果日期连续三天相隔三天怎么办。但我使用的确切数据每人只有 2 个值..

谢谢!

【问题讨论】:

    标签: python pandas datetime group-by pandas-groupby


    【解决方案1】:

    我会将其转换为 datetime 列,然后使用 pd.TimeGrouper

    dates =  pd.to_datetime(df.date, format='%m-%d-%y')
    print(dates)
    0   2017-01-01
    1   2017-01-01
    2   2017-01-01
    3   2017-01-01
    4   2017-01-02
    5   2017-01-02
    6   2017-01-10
    7   2017-02-01
    Name: date, dtype: datetime64[ns]
    
    df = (df.assign(date=dates).set_index('date')
            .groupby(['user_id', pd.TimeGrouper('3D')])
            .sum()
            .reset_index())    
    print(df)
       user_id       date  val
    0        1 2017-01-01    3
    1        2 2017-01-01    2
    2        2 2017-01-10    1
    3        3 2017-01-01    1
    4        3 2017-01-31    1
    

    使用pd.Grouper的类似解决方案:

    df = (df.assign(date=dates)
            .groupby(['user_id', pd.Grouper(key='date', freq='3D')])
            .sum()
            .reset_index())
    print(df)
       user_id       date  val
    0        1 2017-01-01    3
    1        2 2017-01-01    2
    2        2 2017-01-10    1
    3        3 2017-01-01    1
    4        3 2017-01-31    1
    

    更新:TimeGrouper 将在 pandas 的未来版本中被弃用,因此在这种情况下,Grouper 将是首选(感谢提醒,Vaishali!)。

    【讨论】:

    • 我总是害怕触及任何与时间相关的问题......哈哈顺便说一句 +1
    • 太棒了,从来没有用过石斑鱼
    • GrouperTimeGrouper
    • 谢谢 :) @Wen,是的,我过去也经常逃避约会问题。另外,是的,你是对的,唯一的区别是 TimeGrouper 需要索引是日期时间索引。
    • @Wen 这是我的第一选择,但 datetime 列似乎消失了... uff... 我也不喜欢reset_index 但别无选择..
    【解决方案2】:

    我提出了一个非常丑陋的解决方案,但仍然有效......

    df=df.sort_values(['user_id','date'])
    df['Key']=df.sort_values(['user_id','date']).groupby('user_id')['date'].diff().dt.days.lt(3).ne(True).cumsum()
    df.groupby(['user_id','Key'],as_index=False).agg({'val':'sum','date':'first'})
    
    Out[586]: 
       user_id  Key  val       date
    0        1    1    3 2017-01-01
    1        2    2    2 2017-01-01
    2        2    3    1 2017-01-10
    3        3    4    1 2017-01-01
    4        3    5    1 2017-02-01
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-10
      • 2020-12-23
      • 2013-11-04
      • 2021-11-16
      相关资源
      最近更新 更多