如何在Pandas中按ID和CD的连续变化分组并获取起止日期?
解决按ID+连续CD分组并获取起止日期的问题
问题需求
需要按ID分组,同时根据CD列的连续相同值划分独立小组,获取每个连续小组的起始日期和结束日期。原方法直接按ID和CD分组会将同一ID下非连续的同CD记录合并,无法满足需求。
原始数据集
import pandas as pd import numpy as np df = pd.DataFrame({'ID': [1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2], 'DATE': ['1/1/2015','1/2/2015', '1/3/2015','1/4/2015','1/5/2015','1/6/2015','1/7/2015','1/8/2015', '1/9/2016','1/2/2015','1/3/2015','1/4/2015','1/5/2015','1/6/2015','1/7/2015'], 'CD': ['A','A','A','A','B','B','A','A','C','A','A','A','A','A','A']})
原方法的问题
原代码通过df.groupby(['ID','CD']).agg(...)分组时,会将同一ID下所有同CD的记录归为一组,例如ID=1中,1/1-1/4的A和1/7-1/8的A会被合并,忽略了中间的B,无法区分连续的CD分组。
正确解决方案
核心思路是创建一个连续分组标识,对每个ID,当CD值发生变化时,分组标识递增,以此区分非连续的同CD小组。
步骤1:转换日期格式
将DATE列转换为日期类型,确保后续能正确计算最小/最大值:
df['DATE'] = pd.to_datetime(df['DATE'])
步骤2:生成连续分组标识
# 对每个ID,判断当前行CD是否与上一行不同,生成布尔值后累加得到唯一分组ID df['group_id'] = df.groupby('ID')['CD'].apply(lambda x: x.ne(x.shift()).cumsum())
步骤3:分组聚合起止日期
按ID、CD和group_id分组,聚合每个小组的起始和结束日期,最后移除辅助列:
result = df.groupby(['ID', 'CD', 'group_id']).agg( Start_Date=('DATE', 'min'), End_Date=('DATE', 'max') ).reset_index().drop(columns='group_id')
最终结果
ID CD Start_Date End_Date 0 1 A 2015-01-01 2015-01-04 1 1 B 2015-01-05 2015-01-06 2 1 A 2015-01-07 2015-01-08 3 1 C 2016-01-09 2016-01-09 4 2 A 2015-01-02 2015-01-07
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

