基于多条件匹配替换DataFrame指定列的最优方法
问题描述
现有两个Pandas DataFrame:
df1
| old code | new code | date | material |
|---|---|---|---|
| a10 | a11 | 01.01.2010 | mat1 |
| a10 | a11 | 01.01.2010 | mat2 |
| b10 | b11 | 01.01.2011 | mat1 |
df2
| code | date | material |
|---|---|---|
| a10 | 01.01.2008 | mat1 |
| a10 | 01.01.2007 | mat2 |
| a10 | 01.01.2012 | mat2 |
| b10 | 01.01.2005 | mat1 |
需求
当同时满足以下条件时,将df2中的code替换为df1对应的new code:
- df1['old code'] == df2['code']
- df2['date'] ≤ df1['date']
- df1['material'] == df2['material']
最终期望输出:
| code | date | material |
|---|---|---|
| a11 | 01.01.2008 | mat1 |
| a11 | 01.01.2007 | mat2 |
| a10 | 01.01.2012 | mat2 |
| b11 | 01.01.2005 | mat1 |
最优实现方法
这里用Pandas结合Numpy的方案,逻辑清晰且性能高效,适合中等规模的数据:
完整代码
import pandas as pd import numpy as np # 1. 转换日期格式为datetime(原数据是dd.mm.yyyy字符串,无法直接比较) df1['date'] = pd.to_datetime(df1['date'], format='%d.%m.%Y') df2['date'] = pd.to_datetime(df2['date'], format='%d.%m.%Y') # 2. 左连接df2和df1,匹配code+material的对应关系 merged = df2.merge( df1[['old code', 'new code', 'date', 'material']], left_on=['code', 'material'], right_on=['old code', 'material'], how='left', suffixes=('', '_df1') # 区分两个表的date列 ) # 3. 根据日期条件替换code merged['code'] = np.where( merged['date'] <= merged['date_df1'], # 满足日期条件时替换 merged['new code'], merged['code'] # 不满足则保留原code ) # 4. 整理结果,恢复原日期格式并保留目标列 result = merged[['code', 'date', 'material']] result['date'] = result['date'].dt.strftime('%d.%m.%Y') print(result)
代码解释
- 日期格式转换:必须把字符串类型的日期转为
datetime,否则无法进行大小比较,这里指定format='%d.%m.%Y'匹配原数据的日.月.年格式。 - 左连接匹配:通过
code(df2)和old code(df1)、material作为连接键,确保只匹配同物料同旧编码的记录,左连接保证df2的所有行都被保留。 - 条件替换:用
np.where做向量式判断,比循环遍历效率高得多,直接批量处理所有行的替换逻辑。 - 结果整理:过滤掉不需要的中间列,把日期转回原字符串格式,得到最终符合要求的DataFrame。
内容的提问来源于stack exchange,提问作者Alexis
相关产品推荐
相关产品推荐

