如何按ID分组,基于6个月前同列值修改Pandas的Lifecycle ID
解决方案
方法一:分组遍历(直观易懂)
先对数据按ID分组并按Date排序,再对每个分组内的记录检查其6个月前是否存在同ID且Lifecycle ID=5的记录,满足条件则将当前记录的Lifecycle ID改为6。
import pandas as pd import datetime # 原始数据 df = pd.DataFrame({'ID': [1, 2, 1, 1], 'Date' : [datetime.date(year=2022,month=5,day=1), datetime.date(year=2022,month=11,day=1), datetime.date(year=2022,month=10,day=1), datetime.date(year=2022,month=11,day=1)], "Lifecycle ID": [5,5,5,5]}) # 转换Date列为datetime类型,方便日期计算 df['Date'] = pd.to_datetime(df['Date']) # 按ID分组并按日期排序 df = df.sort_values(['ID', 'Date']).reset_index(drop=True) def update_lifecycle(group): # 计算每条记录6个月前的日期 group['6_months_ago'] = group['Date'] - pd.DateOffset(months=6) # 遍历每条记录,检查匹配条件 for idx, row in group.iterrows(): # 查找同组内日期等于6个月前且Lifecycle ID为5的记录 has_match = not group[(group['Date'] == row['6_months_ago']) & (group['Lifecycle ID'] == 5)].empty if has_match: group.at[idx, 'Lifecycle ID'] = 6 # 移除辅助列 return group.drop('6_months_ago', axis=1) # 应用分组处理 result_df = df.groupby('ID', group_keys=False).apply(update_lifecycle) print(result_df)
方法二:合并匹配(高效适合大数据量)
通过创建辅助表,将原记录的日期后推6个月作为匹配键,与原表合并后直接判断条件并更新,避免遍历提升效率。
import pandas as pd import datetime # 原始数据 df = pd.DataFrame({'ID': [1, 2, 1, 1], 'Date' : [datetime.date(year=2022,month=5,day=1), datetime.date(year=2022,month=11,day=1), datetime.date(year=2022,month=10,day=1), datetime.date(year=2022,month=11,day=1)], "Lifecycle ID": [5,5,5,5]}) # 转换Date列为datetime类型 df['Date'] = pd.to_datetime(df['Date']) # 创建辅助表:将原记录的日期后推6个月,作为后续匹配的目标日期 temp_df = df.copy() temp_df['Match_Date'] = temp_df['Date'] + pd.DateOffset(months=6) temp_df = temp_df[['ID', 'Match_Date', 'Lifecycle ID']].rename(columns={'Lifecycle ID': 'Prev_Lifecycle'}) # 合并原表与辅助表,匹配ID和当前日期=辅助表的Match_Date merged_df = df.merge(temp_df, left_on=['ID', 'Date'], right_on=['ID', 'Match_Date'], how='left') # 根据匹配结果更新Lifecycle ID merged_df['Lifecycle ID'] = merged_df.apply( lambda x: 6 if pd.notna(x['Prev_Lifecycle']) and x['Prev_Lifecycle'] == 5 else x['Lifecycle ID'], axis=1 ) # 清理多余列并排序 result_df = merged_df.drop(['Match_Date', 'Prev_Lifecycle'], axis=1).sort_values(['ID', 'Date']).reset_index(drop=True) print(result_df)
输出结果
两种方法都会得到如下结果:
ID Date Lifecycle ID 0 1 2022-05-01 5 1 1 2022-10-01 5 2 1 2022-11-01 6 3 2 2022-11-01 5
内容的提问来源于stack exchange,提问作者FriendlyGuy
相关产品推荐
相关产品推荐

