如何用Pandas基于其他列条件修改列值?解决日期重叠问题
Pandas优化:消除同一ID日期重叠的非循环实现
问题示例
原始DataFrame
start_date end_date id 22-07-2022 28-07-2022 A 22-07-2022 28-07-2022 B 22-07-2022 17-08-2022 A
期望结果
start_date end_date id 22-07-2022 28-07-2022 A 22-07-2022 28-07-2022 B 29-07-2022 17-08-2022 A
需求说明
同一id最多对应两行数据,初始start_date相同,需要把同一id中最早的end_date加1天,替换另一行的start_date,避免日期重叠。目前用循环实现,想找更符合Python风格的Pandas方法。
实现思路与代码
转换日期格式
先把字符串类型的日期列转成Pandas的datetime格式,这是日期操作的前提:df[['start_date', 'end_date']] = df[['start_date', 'end_date']].apply(pd.to_datetime, format='%d-%m-%Y')分组处理日期
利用groupby按id分组,针对每个分组做日期调整,有两种简洁写法:方法一:自定义分组处理函数
def adjust_group_dates(group): if len(group) == 2: # 取当前组最早的end_date earliest_end = group['end_date'].min() # 找到组内start_date和初始值相同、且end_date不是最早的行,替换start_date mask = (group['start_date'] == group['start_date'].iloc[0]) & (group['end_date'] != earliest_end) group.loc[mask, 'start_date'] = earliest_end + pd.Timedelta(days=1) return group df = df.groupby('id', group_keys=False).apply(adjust_group_dates)方法二:结合rank和transform简化
# 给每个id下的end_date排名,1代表最早的日期 df['end_rank'] = df.groupby('id')['end_date'].rank(method='min', ascending=True) # 对排名为2的行,将start_date替换为同组最早end_date加1天 df.loc[df['end_rank'] == 2, 'start_date'] = df.groupby('id')['end_date'].transform(lambda x: x.min() + pd.Timedelta(days=1)) # 删除临时排名列 df = df.drop('end_rank', axis=1)转回字符串格式(可选)
如果需要把日期转回原字符串格式:df[['start_date', 'end_date']] = df[['start_date', 'end_date']].dt.strftime('%d-%m-%Y')
内容的提问来源于stack exchange,提问作者imatiasmb
相关产品推荐
相关产品推荐

