如何按ID与周分组统计连续日期的数量?
问题描述
现有如下用户活动数据的DataFrame:
| ID | week | date |
|---|---|---|
| 1 | 1 | 20/07/22 |
| 1 | 2 | 28/07/22 |
| 1 | 2 | 30/07/22 |
| 1 | 3 | 04/08/22 |
| 1 | 3 | 05/08/22 |
| 2 | 2 | 26/07/22 |
| 2 | 2 | 27/07/22 |
| 2 | 3 | 04/08/22 |
需要按ID和week分组,统计每组内连续日期的总数量,输出要求每个ID对应每周一行,预期输出如下:
| ID | week | count_consecutive |
|---|---|---|
| 1 | 1 | 0 |
| 1 | 2 | 0 |
| 1 | 3 | 2 |
| 2 | 2 | 2 |
| 2 | 3 | 0 |
实现方案
使用Pandas可按以下步骤完成需求:
步骤1:转换日期格式并排序
先将字符串类型的date列转为datetime格式,保证日期计算的准确性;同时按ID、week、date排序,确保组内日期顺序正确:
import pandas as pd # 构造原始数据 df = pd.DataFrame({ 'ID': [1,1,1,1,1,2,2,2], 'week': [1,2,2,3,3,2,2,3], 'date': ['20/07/22','28/07/22','30/07/22','04/08/22','05/08/22','26/07/22','27/07/22','04/08/22'] }) # 转换日期格式(匹配原始日/月/年的格式) df['date'] = pd.to_datetime(df['date'], format='%d/%m/%y') # 按ID、周、日期排序 df = df.sort_values(['ID', 'week', 'date']).reset_index(drop=True)
步骤2:分组计算连续日期
按ID和week分组后,对每个组内的日期计算相邻差值,标记连续日期的分组,最后统计连续日期的总数量:
def count_consecutive_dates(group): if len(group) < 2: return 0 # 计算相邻日期的天数差 diffs = group['date'].diff().dt.days # 将非连续的位置作为分组边界,划分连续日期组 consecutive_groups = (diffs != 1).cumsum() # 统计每个连续组的长度,仅累加长度≥2的组的总数量 consecutive_counts = consecutive_groups.value_counts() total = consecutive_counts[consecutive_counts >=2].sum() return total # 分组应用函数,生成结果 result = df.groupby(['ID', 'week']).apply(count_consecutive_dates).reset_index(name='count_consecutive')
步骤3:验证输出
运行代码后,result的输出与预期完全一致:
print(result) # 输出: # ID week count_consecutive # 0 1 1 0 # 1 1 2 0 # 2 1 3 2 # 3 2 2 2 # 4 2 3 0
关键逻辑说明
- 组内日期数不足2时,直接返回0(无连续可能)
- 用
diff()计算相邻日期差,差值为1天则判定为连续 - 通过
cumsum()将连续日期划分为同一组,仅统计长度≥2的组的总数量(对应连续日期的实际个数)
内容的提问来源于stack exchange,提问作者kri
相关产品推荐
相关产品推荐

