在Python-pandas中计算连续天数

2 投票
4 回答
75 浏览
提问于 2025-04-12 16:13

有一个表格,里面记录了不同客户的访问日期和客户ID。表格如下。有些客户会连续几天来,停几天后再连续几天来。我想计算每个客户的连续访问天数。在我的例子中,每个客户可能会有几段连续的天数。例如,客户1有3天是连续的,然后又有4天是连续的。我想知道怎么才能得到所有这些连续天数的数字,并找出其中最大的一个。

id  visit_date
1   1/2/2022
1   1/3/2022
1   1/4/2022
1   1/7/2022
1   1/8/2022
1   1/9/2022
1   1/10/2022
2   1/1/2022
2   1/2/2022
2   1/4/2022
2   1/6/2022
2   1/7/2022
2   1/8/2022
2   1/9/2022
2   1/10/2022
3   1/3/2022
3   1/4/2022
3   1/5/2022
4   1/3/2022
4   1/4/2022
4   1/8/2022

我尝试了不同的方法,但没有找到任何解决方案。我期望的结果是:

id  consecutive_days
1   3
1   4
2   2
2   5
3   2
4   0

4 个回答

0

假设每个客户的日期都是按顺序排列的,你可以计算每一行之间的差值,然后对每组中差值等于1的行进行求和。

consecutive_days_per_id = df.groupby('id').apply(lambda group: (pd.to_datetime(group['date']).dt.day.diff() == 1).sum())

注意:如果你的列已经是日期时间类型,就可以忽略“pd.to_datetime()”这一部分。

0

代码

grp = (pd.to_datetime(df['visit_date'])
         .groupby(df['id']).diff().ne('1day')
         .groupby(df['id']).cumsum()
)


out = (df.groupby(['id', grp]).size()[lambda x: x > 1]
       .droplevel(1).reset_index(name='consecutive_days')
)

输出:

    id  consecutive_days
0   1   3
1   1   4
2   2   2
3   2   5
4   3   3
5   4   2

获取最大的一个

result = out.groupby('id').max()

结果:

    consecutive_days
id  
1   4
2   5
3   3
4   2
0

如果你只关心最大值的话,可以省去使用两次 groupby 的步骤,直接用 numpy 的聚合函数,这在处理大数据时会更高效:

out = (pd
   .to_datetime(df['visit_date'], dayfirst=False)
   .groupby(df['id'])
   .agg(lambda g: np.diff(np.nonzero(np.r_[g.diff().ne('1d'), len(g)])[0]).max())
   #.reset_index(name='consecutive_days') # optional
)

输出结果:

id
1    4
2    5
3    3
4    2
Name: visit_date, dtype: int64

以框架形式输出:

   id  consecutive_days
0   1                 4
1   2                 5
2   3                 3
3   4                 2

聚合前的中间结果:

id
1       [3, 4]
2    [2, 1, 5]
3          [3]
4       [2, 1]
Name: visit_date, dtype: object

最后,如果你想排除 1,可以在聚合之后再处理(如果是 Series,可以用 out[out>1],如果是 DataFrame,可以用 out.query('consecutive_days>1')

撰写回答