如何高效遍历大行数DataFrame?替代for循环的优化方案
高效实现DataFrame按SAP Order ID同步指定列(替代双重for循环)
原代码的问题
- 时间复杂度极高:双重for循环的时间复杂度为O(n*m),数据量较大时会导致运行时间急剧增加,完全不适合大数据场景。
- 赋值逻辑错误:当前代码只要找到任意一对匹配的SAP Order ID,就会把
df的整列直接替换为df2的整列,而非给对应匹配行赋值,这会导致所有数据被错误覆盖,不符合需求。
高效解决方案
以下两种方法均采用pandas的向量化操作,时间复杂度为O(n+m),能大幅提升处理速度:
方法一:使用merge左连接后更新
适合需要保留df所有原有行,同时匹配df2对应数据的场景:
import pandas as pd # 读取原始数据 df = pd.read_excel('1.xlsx', sheet_name='1', header=0) df2 = pd.read_excel('2.xlsx', sheet_name='2', header=0) # 从df2中提取需要同步的列和匹配键 sync_data = df2[['SAP Order ID', 'FECHA DE DESPACHO', 'NUMERO DE GUIA/FACTURA']] # 左连接:保留df的全部行,匹配df2中对应SAP Order ID的数据 merged_result = df.merge(sync_data, on='SAP Order ID', how='left', suffixes=('', '_from_df2')) # 更新目标列:有匹配值则用df2的数据,无匹配则保留df原有值 df['FECHA DE DESPACHO'] = merged_result['FECHA DE DESPACHO_from_df2'].combine_first(merged_result['FECHA DE DESPACHO']) df['N° Guía Despacho / Factura'] = merged_result['NUMERO DE GUIA/FACTURA'].combine_first(merged_result['N° Guía Despacho / Factura'])
方法二:使用map值映射(适用于df2的SAP Order ID唯一的场景)
如果df2中的SAP Order ID无重复值,可通过映射实现更简洁的同步:
import pandas as pd # 读取原始数据 df = pd.read_excel('1.xlsx', sheet_name='1', header=0) df2 = pd.read_excel('2.xlsx', sheet_name='2', header=0) # 将df2转换为以SAP Order ID为索引的映射关系表 fecha_mapping = df2.set_index('SAP Order ID')['FECHA DE DESPACHO'] guia_mapping = df2.set_index('SAP Order ID')['NUMERO DE GUIA/FACTURA'] # 基于SAP Order ID映射赋值,无匹配则保留原数据 df['FECHA DE DESPACHO'] = df['SAP Order ID'].map(fecha_mapping).combine_first(df['FECHA DE DESPACHO']) df['N° Guía Despacho / Factura'] = df['SAP Order ID'].map(guia_mapping).combine_first(df['N° Guía Despacho / Factura'])
关键说明
- 两种方法均避免了循环,利用pandas底层的C语言向量化操作优化处理速度,远快于双重循环。
- 若需同步更多列,只需在
sync_data(方法一)或映射表(方法二)中添加对应列即可,扩展性强。
内容的提问来源于stack exchange,提问作者Jorge Aliguery
相关产品推荐
相关产品推荐

