2017-10-19 164 views
2

我期待分两列:user_id和日期;但是,如果日期足够接近,我希望能够相应地考虑同一组和组中的两个条目。日期是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个值每人..

谢谢!

回答

5

我会将此转换为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将在未来的版本中被弃用大熊猫,所以Grouper在这种情况下是首选(感谢Vaishali!)。

+1

我总是害怕接触相关问题任何时候...... LOL顺便说一句+1 – Wen

+1

最好的,从来没有使用过石斑鱼莫名其妙 – Vaishali

+0

'Grouper'是'TimeGrouper' – Wen

0

我带着一个很丑陋的解决方案,但仍然工作...

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