如何按日期分组并查找连续的天数

时间:2018-08-23 15:33:05

标签: python pandas numpy dataframe

所以我有一个像这样的表

product date_purchased
apple   2018-08-01
apple   2018-08-02
apple   2018-08-03
apple   2018-08-10
apple   2018-08-11
banana  2018-08-14

我正在寻找连续几天购买该产品的次数。喜欢

apple   2018-08-01  1
apple   2018-08-02  2
apple   2018-08-03  3
apple   2018-08-10  1
apple   2018-08-11  2
banana  2018-08-14  1

产品中的第一列,第二列是购买的最后日期,第三列是连续购买的日期。

[EDIT]:更改了输出格式

2 个答案:

答案 0 :(得分:2)

使用diffcumsum创建新密钥,然后我们可以groupby agg

df.date_purchased=pd.to_datetime(df.date_purchased)
df['Newkey']=df.date_purchased.diff().dt.days.ne(1).cumsum()
df
Out[358]: 
  product date_purchased  Newkey
0   apple     2018-08-01       1
1   apple     2018-08-02       1
2   apple     2018-08-03       1
3   apple     2018-08-10       2
4   apple     2018-08-11       2
5  banana     2018-08-14       3
df.groupby(['product','Newkey'])['date_purchased'].agg(['last','count'])
Out[359]: 
                     last  count
product Newkey                  
apple   1      2018-08-03      3
        2      2018-08-11      2
banana  3      2018-08-14      1

更新

df.date_purchased=pd.to_datetime(df.date_purchased)
df['Newkey']=df.date_purchased.diff().dt.days.ne(1).cumsum()
df
Out[384]: 
  product date_purchased  Newkey
0   apple     2018-08-01       1
1   apple     2018-08-02       1
2   apple     2018-08-03       1
3   apple     2018-08-10       2
4   apple     2018-08-11       2
5  banana     2018-08-14       3
df.groupby(['Newkey']).cumcount()+1
Out[385]: 
0    1
1    2
2    3
3    1
4    2
5    1
dtype: int64

答案 1 :(得分:2)

查找日期更改的时间,并使用date_groupsshift函数创建cumsum。然后,您可以使用熊猫提供的多重聚合功能按productdate_group进行分组。

最后格式化和重命名列以匹配预期的输出:

import datetime as dt

(df.assign(date_group=lambda x: (x.date_purchased != x.date_purchased.shift(1)
                                  + dt.timedelta(days=1)).cumsum()
           )
 .groupby(['product', 'date_group'])['date_purchased'].agg(['last', 'count'])
 .reset_index(level=-1, drop=True)
 .rename(columns={'last': 'last_date_purchased',
                 'count': 'times_in_a_row'})
)


         last_date_purchased  times_in_a_row
product                                    
apple            2018-08-03               3
apple            2018-08-11               2
banana           2018-08-14               1

编辑:

所需的输出稍微改变了要遵循的策略。上一个比较简单,对于lambda函数的过度使用,我深表歉意。我确定可以使用一些pipe

从某种意义上说,代码发生了变化,因为我们现在不计算每个group_date中的元素,而是每天计算单个key中的元素。同样,我们只需要groupby就可以使用transform函数的杠杆作用。

(df.assign(date_group=lambda x: (x.date_purchased != x.date_purchased.shift(1)
                              + dt.timedelta(days=1)).cumsum(),
        key=1,
        times_in_a_row=lambda x: x.groupby(['product', 'date_group'])
                                  .transform(lambda x: x.cumsum())
       )
[['product', 'date_purchased', 'times_in_a_row']]
)

  product date_purchased  times_in_a_row
0   apple     2018-08-01               1
1   apple     2018-08-02               2
2   apple     2018-08-03               3
3   apple     2018-08-10               1
4   apple     2018-08-11               2
5  banana     2018-08-14               1
相关问题