
本文介绍如何使用 pandas 和 numpy 高效识别并统计每位客户的所有连续访问区间长度,并提取最长连续天数,适用于电商、saas 用户行为分析等场景。
本文介绍如何使用 pandas 和 numpy 高效识别并统计每位客户的所有连续访问区间长度,并提取最长连续天数,适用于电商、saas 用户行为分析等场景。
在用户行为分析中,识别“连续活跃天数”是评估用户粘性与留存质量的关键指标。给定含 id(客户ID)和 visit_date(访问日期)的原始数据表,目标不是简单求总天数,而是按客户分组,检测所有连续访问段(即日期无间隔的递增序列),分别计算每段长度,并最终获取最大值——例如客户 1 在 2022-01-02/03/04(3 天)和 2022-01-07/08/09/10(4 天)有两段连续访问,应返回 4。
核心思路是:将日期转为有序时间序列 → 计算相邻日期差 → 用差值是否等于 1 天作为“连续性断点”的标志 → 基于断点对访问记录分组 → 统计每组长度。pandas 提供了简洁高效的向量化实现方式。
以下为完整可运行代码(含数据构造、处理与验证):
import pandas as pd
import numpy as np
# 构造示例数据(注意:原始字符串日期需统一格式)
df = pd.DataFrame({
'id': [1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,4,4,4],
'visit_date': [
'1/2/2022', '1/3/2022', '1/4/2022', '1/7/2022', '1/8/2022',
'1/9/2022', '1/10/2022', '1/1/2022', '1/2/2022', '1/4/2022',
'1/6/2022', '1/7/2022', '1/8/2022', '1/9/2022', '1/10/2022',
'1/3/2022', '1/4/2022', '1/5/2022', '1/3/2022', '1/4/2022', '1/8/2022'
]
})
# 步骤 1:转换为 datetime(自动识别月/日/年,dayfirst=False 表示 MM/DD/YYYY)
df['visit_date'] = pd.to_datetime(df['visit_date'], format='%m/%d/%Y')
# 步骤 2:按 id 分组,对 visit_date 排序后计算连续段(关键逻辑)
def get_consecutive_lengths(series):
if len(series) == 0:
return []
s_sorted = series.sort_values().reset_index(drop=True)
# 计算相邻日期差(单位:天),标记非连续位置(diff != '1D')
diffs = s_sorted.diff().dt.days != 1
# 生成分组标识:每次 diff 为 True 时 +1,形成连续段 ID
group_ids = diffs.cumsum()
# 按 group_ids 分组,统计每段长度(即连续天数)
lengths = group_ids.value_counts().sort_index().values
return list(lengths)
# 步骤 3:应用函数并展开结果(获取所有连续段长度)
consec_list = df.groupby('id')['visit_date'].apply(get_consecutive_lengths).explode().reset_index(name='consecutive_days')
consec_list['consecutive_days'] = consec_list['consecutive_days'].astype(int)
# 可选:过滤掉单日访问(即连续天数=1,通常不视为“连续行为”)
consec_list = consec_list[consec_list['consecutive_days'] > 1].copy()
# 步骤 4:获取每位客户的最长连续天数
max_consec = consec_list.groupby('id')['consecutive_days'].max().reset_index(name='max_consecutive_days')
print("所有连续段(过滤掉单日):")
print(consec_list)
print("\n每位客户最长连续天数:")
print(max_consec)
输出示例:
所有连续段(过滤掉单日): id consecutive_days 0 1 3 1 1 4 2 2 2 3 2 5 4 3 3 5 4 2 每位客户最长连续天数: id max_consecutive_days 0 1 4 1 2 5 2 3 3 3 4 2
✅ 关键注意事项:
- 日期格式必须规范:pd.to_datetime() 建议显式指定 format(如 '%m/%d/%Y'),避免因地区设置导致解析错误;
- 空组/单客户处理:若某客户仅访问 1 天,get_consecutive_lengths 返回 [1],可通过 .query('consecutive_days > 1') 过滤;
- 性能优化:对超大数据集(百万行以上),可改用 np.diff + np.nonzero 的纯 NumPy 方案(如答案中所示),但可读性略低;
- 业务语义校准:“连续”默认指自然日连续(含周末),如需排除节假日,需先构建工作日日历并做预过滤。
掌握该方法后,你不仅能快速提取最长连续天数,还可进一步拓展:计算连续段数量、平均连续长度、首次/末次连续区间起止时间等,为精细化用户分层与运营策略提供坚实数据基础。










