使用熊猫按日期范围分组
Posted
技术标签:
【中文标题】使用熊猫按日期范围分组【英文标题】: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 个值..
谢谢!
【问题讨论】:
【参考方案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 太棒了,从来没有用过石斑鱼Grouper
是TimeGrouper
谢谢 :) @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
【讨论】:
以上是关于使用熊猫按日期范围分组的主要内容,如果未能解决你的问题,请参考以下文章