如何用Pandas高效合并用户重叠/连续的订阅记录?
用Pandas高效合并重叠/连续订阅记录
直接上解决方案,核心思路是按用户分组后,通过标记连续/重叠的订阅区间,再聚合得到合并后的记录,完全避免嵌套循环,效率拉满。
步骤1:数据预处理
先确保日期字段是datetime类型,然后按User和Subscription Start排序,保证同用户的订阅按时间顺序排列。
import pandas as pd # 构造测试数据(模拟你的数据集) data = { "User": ["John", "John", "Jane", "Jane", "Jane"], "Subscription Start": ["2024-01-01", "2024-01-31", "2024-02-01", "2024-03-02", "2024-04-01"], "Subscription Length": [30, 30, 30, 30, 30], "Subscription End": ["2024-01-30", "2024-02-29", "2024-02-29", "2024-03-31", "2024-04-30"] } df = pd.DataFrame(data) # 转换日期字段为datetime类型 df["Subscription Start"] = pd.to_datetime(df["Subscription Start"]) df["Subscription End"] = pd.to_datetime(df["Subscription End"]) # 按用户和订阅开始时间排序 df = df.sort_values(["User", "Subscription Start"]).reset_index(drop=True)
步骤2:标记独立订阅组
对每个用户,判断当前订阅的开始时间是否早于或等于上一个订阅的结束时间+1天(处理连续的情况),如果是则属于同一组,否则新建组。用cumsum()生成组ID。
# 按用户分组,计算组标记 df["Group"] = df.groupby("User").apply( lambda x: (x["Subscription Start"] > x["Subscription End"].shift() + pd.Timedelta(days=1)).cumsum() ).reset_index(level=0, drop=True)
步骤3:聚合得到合并后的记录
按User和Group分组,聚合出合并后的开始时间、结束时间,以及总时长。
merged_df = df.groupby(["User", "Group"], as_index=False).agg( Merged_Start=("Subscription Start", "min"), Merged_End=("Subscription End", "max"), Total_Length=("Subscription Length", "sum") ) # 可选:删除Group列(如果不需要的话) merged_df = merged_df.drop("Group", axis=1)
关键说明
- 这里用
pd.Timedelta(days=1)处理连续订阅的判断,你可以根据实际需求调整:如果认为订阅结束当天与下一个开始当天算连续,就去掉+ pd.Timedelta(days=1) - 整个过程都是Pandas向量式操作,比嵌套循环效率高几个数量级,数据量大时优势尤为明显
内容的提问来源于stack exchange,提问作者Zera
相关产品推荐
相关产品推荐

