Pandas计算最大连续间隔时间

日常统计中总会遇到需要统计和周期有关的数据,如用户连续登录天数,事件发生的连续性等。
样本数据是用户的ID和抽奖日期,准备计算出每个用户的连续抽奖最大间隔时间,我先说一下我的思路。先将根据用户ID将用户分组并按照日期排序,对相邻的日期进行比较,差异为1天的即为连续数据,对连续数据进行计数即可计算出最大的时间间隔。

数据样本

import pandas as pd
df = pd.read_csv(r'tmp\draw.csv')
df
draw_date weixin_id
0 2021-05-25 751478029716439040
1 2021-05-28 751478029716439040
2 2021-06-08 751478029716439040
3 2021-06-09 751478029716439040
4 2021-06-15 639062248681259008
5 2021-06-16 639062248681259008
6 2021-06-17 639062248681259008
7 2021-06-18 639062248681259008
8 2021-06-19 639062248681259008
9 2021-06-21 639062248681259008

样本中数据是字符串,我先将日期转成对应的格式

df['draw_date'] = pd.to_datetime(df['draw_date'])

我这里使用shift将日期下移一位,再加上一天和相邻数据进行比较,目的是判断前后两条时间间隔是否相差1天,不相等记为True反之为False

import datetime
for name,group in df.groupby('weixin_id'):
    check = ((group['draw_date'].shift(1) + datetime.timedelta(1)) != group['draw_date'])
    print(check)
4     True
5    False
6    False
7    False
8    False
9     True
Name: draw_date, dtype: bool
0     True
1     True
2     True
3    False
Name: draw_date, dtype: bool

cumsum窗口函数,对上文提到的标记按照行累加,标记为False的情况不会计算

for name,group in df.groupby('weixin_id'):
    check = ((group['draw_date'].shift(1) + datetime.timedelta(1)) != group['draw_date'])
    cumsum = check.cumsum()
    print(cumsum)
4    1
5    1
6    1
7    1
8    1
9    2
Name: draw_date, dtype: int32
0    1
1    2
2    3
3    3
Name: draw_date, dtype: int32

value_counts对上文累计的数据进行分组计数,可以算出每段时间的间隔天数,按照我们的需求取最大的即可

for name,group in df.groupby('weixin_id'):
    check = ((group['draw_date'].shift(1) + datetime.timedelta(1)) != group['draw_date'])
    cumsum = check.cumsum()
    value_counts = cumsum.value_counts()
    print(value_counts)    
1    5
2    1
Name: draw_date, dtype: int64
3    2
2    1
1    1
Name: draw_date, dtype: int64

上边的循环代码可以用agg替代

import datetime
df.groupby('weixin_id').agg(
    lambda group:
        ((group.shift(1) + datetime.timedelta(1)) != group).cumsum().value_counts().max()
)

draw_date
weixin_id
639062248681259008 5
751478029716439040 2

前后数据比较也可直接使用diff函数,该函数可算出前后两条数据相减的结果

df.groupby('weixin_id').agg(
    lambda group :
        group.diff(1).map(
            lambda d:d.days - 1).fillna(0).cumsum().value_counts().max()
    )


draw_date
weixin_id
639062248681259008 5
751478029716439040 2

参考文档

【pandas】计算最大连续间隔时间


Pandas计算最大连续间隔时间
https://blog.yjll.blog/post/15886092.html
作者
简斋
发布于
2021年9月27日
许可协议