Python处理Excel日期匹配代码运行缓慢且结果不符预期求助
Pandas处理Excel日期范围匹配:效率优化与结果修正
问题描述
现有两个Excel表格:
coilid(约3000行):需用每行的DT_START日期匹配范围retifica:用Data de entrada(入厂日期)和Data de Saída(出厂日期)作为匹配范围
需求:
- 若
DT_START落在retifica的日期范围内,导出该行coilid数据 +retifica的ret、cilindro单元格 - 若不匹配,仅导出
coilid行
原代码运行耗时极长,且结果不符合预期,代码如下:
import pandas as pd retifica = pd.read_excel('C:\\Arquivoparamim.xlsx', sheet_name='Planilha1') retifica = retifica.sort_values(by=['Data Retífica'], ascending=True) coilid = pd.read_excel('C:\\Arquivoparamim.xlsx', sheet_name='Planilha2') coilid = coilid.sort_values(by=['DT_START'], ascending=True) match=pd.DataFrame() for x in range (coilid.shape[0]): for y in range (retifica.shape[0]): if (coilid.iloc[x,2]>retifica.iloc[y,16])&(coilid.iloc[x,2]<retifica.iloc[y,18]): matchaux = [coilid.iloc[x],retifica.iloc[y]] else: matchaux = [coilid.iloc[x]] match=match.append(matchaux) break match.to_excel('Libraries\\Pictures\\aline.xlsx')
原代码核心问题
- 双重循环效率极低:3000行
coilid× 3000行retifica= 900万次迭代,属于O(n*m)复杂度,完全违背Pandas向量化操作的设计逻辑 df.append()性能灾难:循环中反复调用append会不断创建新的DataFrame,内存开销大且速度极慢- 逻辑错误:内层循环的
break仅检查retifica的第一行,未遍历所有可能的匹配项;else分支的append位置错误,导致结果重复或缺失 - 日期类型未校验:若Excel读取的日期是字符串格式,直接比较会出现逻辑错误(字符串比较≠日期比较)
优化解决方案
利用Pandas的merge_asof(适合排序后的时间范围匹配),实现O(n+m)线性复杂度的高效匹配,同时修正逻辑:
修正后代码
import pandas as pd # 读取数据 retifica = pd.read_excel('C:\\Arquivoparamim.xlsx', sheet_name='Planilha1') coilid = pd.read_excel('C:\\Arquivoparamim.xlsx', sheet_name='Planilha2') # 1. 转换日期列为datetime类型(关键:避免字符串比较错误) retifica['Data de entrada'] = pd.to_datetime(retifica['Data de entrada']) retifica['Data de Saída'] = pd.to_datetime(retifica['Data de Saída']) coilid['DT_START'] = pd.to_datetime(coilid['DT_START']) # 2. 按匹配日期排序(merge_asof要求必须排序) retifica = retifica.sort_values('Data de entrada') coilid = coilid.sort_values('DT_START') # 3. 用merge_asof做左连接,匹配DT_START >= Data de entrada的最近记录 # 仅保留需要的ret、cilindro列,减少数据量 match = pd.merge_asof( coilid, retifica[['Data de entrada', 'Data de Saída', 'ret', 'cilindro']], left_on='DT_START', right_on='Data de entrada', direction='backward' # 找DT_START之前最近的Data de entrada ) # 4. 过滤出DT_START在[Data de entrada, Data de Saída)范围内的行 # 不匹配的行ret、cilindro会自动为NaN,保留原coilid数据 match = match[(match['DT_START'] < match['Data de Saída']) | match['Data de Saída'].isna()] # 5. 清理不需要的中间列 match = match.drop(['Data de entrada', 'Data de Saída'], axis=1) # 6. 导出结果 match.to_excel('Libraries\\Pictures\\aline.xlsx', index=False)
代码说明
- 日期类型转换:确保所有日期列是
datetime64类型,保证比较逻辑正确 merge_asof高效匹配:利用排序后的线性扫描,避免双重循环,速度提升数十倍- 精准过滤:仅保留
DT_START落在日期范围内的匹配项,未匹配的行自动保留原coilid数据(ret、cilindro为NaN) - 减少冗余数据:仅合并需要的
ret、cilindro列,降低内存占用
内容的提问来源于stack exchange,提问作者Aline De Souza Silva
相关产品推荐
相关产品推荐

