【问题标题】:How to group by date and find consecutive day count如何按日期分组并查找连续天数
【发布时间】:2018-08-29 16:04:12
【问题描述】:

所以我有一张这样的桌子

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

product中的第一列,第二列是最后一次购买的日期,第三列是连续购买的天数。

[编辑]:更改了输出格式

【问题讨论】:

  • 到目前为止你有什么尝试?
  • 我对group by很熟悉,但是我不知道如何连续检查并获得计数。
  • 仅供参考,最好将您的列称为products,因为productproduct 方法冲突

标签: python pandas numpy dataframe


【解决方案1】:

使用diffcumsum创建一个新密钥,然后我们可以groupbyagg

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

【讨论】:

  • 太棒了。请务必按productsdate_purchased 对数据框进行排序,否则diff 可能不起作用。
  • 太棒了!!。如何编辑它以显示每个日期的输出天数。
  • @JohnConstantine 你的意思是输出天数?
  • @Wen 对不起,我修改了问题中的输出。
【解决方案2】:

查找日期何时更改并使用shiftcumsum 函数创建date_groups。然后您可以使用 pandas 提供的多重聚合功能按 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

【讨论】:

  • 太棒了!!。如何编辑它以显示每个日期的输出天数。
  • 非常抱歉我忘记添加导入了。让我编辑。
  • @JohnConstantine 每个日期的输出天数是什么意思?
  • 我修改了有问题的输出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-17
  • 1970-01-01
  • 2021-07-31
  • 1970-01-01
相关资源
最近更新 更多