You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas:分组查询订单号的最长连续序列与末次连续序列

Pandas分组计算订单号最长连续序列与末次连续序列

先看我们的原始数据:

user_idproduct_idorder_number
111
112
113
121
125
211
213
214
215
311
312
316

需求很明确:按user_id和product_id分组,计算两个核心指标:

  • longest_streak:order_number的最长连续无跳过序列长度(如果所有订单号都是孤立的,无连续序列,值为0)
  • last_streak:从最后一个order_number往前数的连续段长度(若最后一个订单号没有前续连续值,值为0)

期望输出结果:

user_idproduct_idlongest_streaklast_streak
1133
1200
2133
3120

实现思路与代码

我把整个实现拆成几个关键步骤,每一步都有明确的作用:

1. 准备数据并确保有序

首先要保证每个分组内的order_number是升序排列的,不然连续序列的判断会出错:

import pandas as pd

# 构建原始DataFrame
data = {
    'user_id': [1,1,1,1,1,2,2,2,2,3,3,3],
    'product_id': [1,1,1,2,2,1,1,1,1,1,1,1],
    'order_number': [1,2,3,1,5,1,3,4,5,1,2,6]
}
df = pd.DataFrame(data)

# 排序:按用户、商品、订单号升序
df = df.sort_values(['user_id', 'product_id', 'order_number']).reset_index(drop=True)

2. 标记连续序列分组

通过计算每个订单号与前一个的差值,判断是否属于同一个连续段:

# 计算当前订单号与前一个的差值
df['diff'] = df.groupby(['user_id', 'product_id'])['order_number'].diff()

# 生成连续段ID:当差值不等于1时,视为新的连续段,用cumsum分配唯一ID
df['segment_id'] = df.groupby(['user_id', 'product_id'])['diff'].apply(lambda x: (x != 1).cumsum())

比如用户1、商品1的订单号1、2、3,差值都是1,会被分到同一个segment_id;而订单号1和5的差值是4,会被分到不同的segment_id。

3. 计算每个连续段的长度

对每个(用户、商品、连续段)分组,统计该段内的订单数量:

df['streak_length'] = df.groupby(['user_id', 'product_id', 'segment_id'])['order_number'].transform('count')

4. 计算最长连续序列

取每个(用户、商品)分组中最大的段长度,若最大长度<=1,说明没有连续序列,设为0:

# 提取每个分组的最大段长度
longest = df.groupby(['user_id', 'product_id'])['streak_length'].max().reset_index()
# 转换为符合需求的longest_streak
longest['longest_streak'] = longest['streak_length'].apply(lambda x: x if x > 1 else 0)
longest = longest.drop('streak_length', axis=1)

5. 计算末次连续序列

找到每个分组的最后一个连续段,判断其长度是否大于1,大于则保留长度,否则设为0:

# 获取每个分组的最后一个连续段ID
last_segment = df.groupby(['user_id', 'product_id'])['segment_id'].last().reset_index()
# 合并得到最后一个段的长度
last_streak_df = pd.merge(
    last_segment, 
    df[['user_id', 'product_id', 'segment_id', 'streak_length']].drop_duplicates(), 
    on=['user_id', 'product_id', 'segment_id']
)
# 转换为符合需求的last_streak
last_streak_df['last_streak'] = last_streak_df['streak_length'].apply(lambda x: x if x > 1 else 0)
last_streak_df = last_streak_df.drop(['segment_id', 'streak_length'], axis=1)

6. 合并结果得到最终输出

把最长和末次连续序列的结果合并起来:

result = pd.merge(longest, last_streak_df, on=['user_id', 'product_id'])
print(result)

运行这段代码后,就能得到你期望的结果啦!


内容的提问来源于stack exchange,提问作者iLoeng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:03:41