在Pandas中按Type分组,基于Start_Date生成Closed_Date列
实现DataFrame新增Closed_Date列的需求
原始数据
import pandas as pd df = pd.DataFrame({ 'Ref_number': [1,2,3,4,5,6,7,8], 'Type': ['A','A','A','B','B','A','B','A'], 'Start_Date': ['02/04/2020','03/04/2020','04/04/2020','03/04/2020','24/04/2020','10/08/2022','10/08/2021','11/09/2022'] })
需求说明
- 按
Type字段分组处理 - 每条数据的
Closed_Date为同Type中,比当前Start_Date大且年月不同的最小Start_Date - 若同Type中无符合条件的日期,则
Closed_Date设为上月最后一天
解决方案代码
# 转换日期列为datetime类型(适配日/月/年格式) df['Start_Date'] = pd.to_datetime(df['Start_Date'], dayfirst=True) # 定义获取上月最后一天的工具函数 def get_last_day_prev_month(date): first_day_current = date.replace(day=1) return first_day_current - pd.Timedelta(days=1) # 分组处理逻辑 def process_type_group(group): # 提取组内唯一日期并排序,减少重复计算 sorted_unique_dates = sorted(group['Start_Date'].unique()) # 为每条数据匹配Closed_Date def match_closed_date(row_date): # 筛选符合条件的候选日期:更大且年月不同 valid_candidates = [d for d in sorted_unique_dates if d > row_date and (d.year != row_date.year or d.month != row_date.month)] if valid_candidates: return min(valid_candidates) else: return get_last_day_prev_month(row_date) group['Closed_Date'] = group['Start_Date'].apply(match_closed_date) return group # 应用分组处理并重置索引 df = df.groupby('Type').apply(process_type_group).reset_index(drop=True) # 转换回原日期字符串格式(日/月/年) df['Start_Date'] = df['Start_Date'].dt.strftime('%d/%m/%Y') df['Closed_Date'] = df['Closed_Date'].dt.strftime('%d/%m/%Y') print(df)
执行结果
Ref_number Type Start_Date Closed_Date 0 1 A 02/04/2020 10/08/2022 1 2 A 03/04/2020 10/08/2022 2 3 A 04/04/2020 10/08/2022 3 4 B 03/04/2020 10/08/2021 4 5 B 24/04/2020 10/08/2021 5 6 A 10/08/2022 11/09/2022 6 7 B 10/08/2021 31/07/2021 7 8 A 11/09/2022 31/08/2022
关键步骤说明
- 日期类型转换:将字符串日期转为datetime,确保日期比较的准确性,避免字符串排序的错误。
- 上月最后一天计算:通过“当月第一天减一天”的方式,无需手动处理不同月份的天数差异,逻辑更通用。
- 分组优化:先提取组内唯一日期并排序,避免对每条数据重复遍历所有日期,提升效率。
- 候选日期筛选:明确区分“日期更大”且“年月不同”两个条件,确保符合需求规则。
内容的提问来源于stack exchange,提问作者sam_rox
相关产品推荐
相关产品推荐

