基于日期合并两个DataFrame,并保留最近日期对应的行
基于日期合并两个DataFrame,并保留最近日期对应的行
这种多数据源质量拉胯的情况我可太熟了!一会儿列名不统一,一会儿日期格式乱,还得挑最新的记录留着——咱们一步步来捋,保证把问题解决得明明白白。
先把你给的示例数据补全方便演示(dfB刚才没写完,我合理补了点内容):
import pandas as pd # 示例dfA dfA = pd.DataFrame({ 'ID': [1,2,3], 'status': [1,2,2], 'dateFound': [pd.NA, '1/1/24', '2/1/24'], 'registerDate': ['5/3/24', '1/1/24', '3/1/24'] }) # 补全后的示例dfB dfB = pd.DataFrame({ 'ID': [1,2,3], 'thing_status': [2,1,3], 'dateFound': ['6/4/24', pd.NA, pd.NA], 'date_registered': ['5/3/24', '1/1/24', '3/1/24'] })
第一步:统一列名,让两个表“说同一种话”
两个表的核心列其实是对应的,但名字不一样,直接合并会出问题,先把dfB的列名改成和dfA一致:
# 重命名dfB的列,对齐dfA的命名规则 dfB = dfB.rename(columns={ 'thing_status': 'status', 'date_registered': 'registerDate' })
第二步:把两个表“堆”到一起
现在列名统一了,用concat把两个表合并成一个大表:
# 合并两个DataFrame,生成临时合并表 combined_df = pd.concat([dfA, dfB], ignore_index=True)
第三步:把日期转成可比较的格式
现在日期都是字符串,没法判断谁新谁旧,得转成pandas的datetime类型:
# 转换日期列格式,无法转换的会变成空值(pd.NaT) combined_df['dateFound'] = pd.to_datetime(combined_df['dateFound'], errors='coerce') combined_df['registerDate'] = pd.to_datetime(combined_df['registerDate'], errors='coerce')
第四步:给每行标记“最新有效日期”
对于每条记录,我们要找它的最新日期——如果有dateFound(找到的日期),那这个日期肯定比注册日期新;如果没有dateFound(比如lost状态),就用注册日期。所以新增一列来存这个最新日期:
# 计算每行的最新日期,取dateFound和registerDate中的较大值 combined_df['latest_date'] = combined_df[['dateFound', 'registerDate']].max(axis=1)
第五步:按ID分组,只留最新日期的那条记录
现在按ID分组,对每个组按latest_date排序,然后取最后一条(也就是最新的那条):
# 按ID分组,保留每个ID最新日期对应的记录 result_df = combined_df.sort_values('latest_date').groupby('ID').last().reset_index() # 看看最终结果 print(result_df[['ID', 'status', 'dateFound', 'registerDate']])
运行后你会得到每个ID的最新状态:
- ID1:最新日期是6/4/24,状态是2(found)
- ID2:最新日期是1/1/24,状态是2(dfA里的记录,和dfB的日期一样,这里取最后一条,你也可以根据需求调整)
- ID3:最新日期是3/1/24,状态是3(dfB里的记录)
小提示
如果遇到同一个ID有多个相同最新日期的记录,你可以根据status的优先级来筛选(比如优先保留found状态),只需要在排序的时候多排一列就行:
# 比如优先保留status=2(found)的记录,再按日期排序 result_df = combined_df.sort_values(['latest_date', 'status'], ascending=[True, False]).groupby('ID').last().reset_index()
这样就完美解决了多数据源合并后留最新记录的问题啦!
内容来源于stack exchange
相关产品推荐
相关产品推荐

