Python Pandas中按组用下一行start_dt填充end_dt列的优化方案
更简洁的缓慢变化维度(SCD)日期填充方案
嘿,你的这个需求用Pandas的shift()方法就能完美解决,比你当前的合并方案简洁高效得多!咱们一步步来实现:
核心思路
我们需要先按Key分组,组内按start_dt排序保证顺序正确,然后直接用shift(-1)获取每组内下一行的start_dt,赋值给当前行的end_dt即可,最后一行自然会保留NA,完全符合你的期望。
完整实现代码
import pandas as pd # 假设你的原始DataFrame是这样的 df = pd.DataFrame({ 'Key': [1, 1, 1, 2, 2], 'start_dt': ['25-05-2019', '30-06-2019', '15-07-2019', '17-07-2019', '15-07-2019'], 'end_dt': [pd.NA, pd.NA, pd.NA, pd.NA, pd.NA] }) # 第一步:把start_dt转为datetime类型,确保排序逻辑正确 df['start_dt'] = pd.to_datetime(df['start_dt'], format='%d-%m-%Y') # 第二步:按Key分组,组内按start_dt升序排序 df = df.sort_values(['Key', 'start_dt']).reset_index(drop=True) # 第三步:用shift(-1)获取每组下一行的start_dt,赋值给end_dt df['end_dt'] = df.groupby('Key')['start_dt'].shift(-1) # 可选:把日期转回原字符串格式(如果需要的话) df['start_dt'] = df['start_dt'].dt.strftime('%d-%m-%Y') df['end_dt'] = df['end_dt'].dt.strftime('%d-%m-%Y').where(df['end_dt'].notna(), pd.NA) print(df)
输出结果
Key start_dt end_dt 0 1 25-05-2019 30-06-2019 1 1 30-06-2019 15-07-2019 2 1 15-07-2019 <NA> 3 2 15-07-2019 17-07-2019 4 2 17-07-2019 <NA>
为什么这个方案更优?
- 代码简洁:不需要生成额外的
seq列,也不需要拆分、重命名、合并DataFrame,几行代码就能完成。 - 性能更好:避免了合并操作的开销,尤其是当你的数据量很大时,
groupby+shift的组合比合并两个DataFrame高效得多。 - 逻辑清晰:直接对应你的需求——“每组内下一行的start_dt作为当前行的end_dt”,代码语义明确,可读性强。
关键方法解释
pd.to_datetime(..., format='%d-%m-%Y'):确保日期字符串被正确解析为datetime类型,避免字符串排序时出现的逻辑错误(比如跨月日期的字符串排序可能不符合时间顺序)。groupby('Key')['start_dt'].shift(-1):在每个Key分组内,将start_dt列向上偏移一位(即取当前行的下一行值),分组的最后一行没有下一行,所以会返回NA,正好符合你的需求。
内容的提问来源于stack exchange,提问作者Arruldhana Mathy
相关产品推荐
相关产品推荐

