优化大型DataFrame匹配性能:替代嵌套for-loop方案咨询
高效匹配DataFrame并生成动态列的解决方案
需求与问题
我有两个DataFrame:df2(约58000行)和sic_tax(1000行),需要完成以下操作:
- 匹配df2与sic_tax的
capex_sic_code列 - 匹配成功后,用sic_tax的
SDG #和Direction (A, PA, PM, M)生成a_b格式的新列名 - 将df2对应行的
% of capex值填入对应新列
当前用嵌套for-loop实现,但58000×1000的迭代量导致运行极慢,现有代码如下:
for index, row in df2.iterrows(): for index2, row2 in sic_tax.iterrows(): if df2.iloc[index][df2.columns.get_loc('capex_sic_code')]==sic_tax.iloc[index2][sic_tax.columns.get_loc('capex_sic_code')]: sdg_code = str(str(sic_tax.iloc[index2][sic_tax.columns.get_loc('SDG #')]))+'_'+str(sic_tax.iloc[index2][sic_tax.columns.get_loc('Direction (A, PA, PM, M)')]) a = df2.iloc[index][df2.columns.get_loc('% of capex')] df2.at[index, sdg_code] = a break
优化方案:用矢量化操作替代嵌套循环
直接用pandas的merge+透视表实现,完全避免逐行迭代,效率提升几个数量级:
步骤1:合并两个DataFrame
只保留需要的字段,通过capex_sic_code关联:
# 合并df2和sic_tax,保留原df2的所有行(匹配不到的字段显示NaN) merged_df = df2[['capex_sic_code', '% of capex']].merge( sic_tax[['capex_sic_code', 'SDG #', 'Direction (A, PA, PM, M)']], on='capex_sic_code', how='left' )
步骤2:生成动态列标识符
把SDG #和Direction拼接成目标格式的列名,同时处理空值:
# 拼接成a_b格式的标识符,处理可能的空值情况 merged_df['identifier'] = merged_df['SDG #'].astype(str) + '_' + merged_df['Direction (A, PA, PM, M)'].astype(str) # 把匹配不到的情况替换成统一标识,比如'Unmatched' merged_df['identifier'] = merged_df['identifier'].replace('nan_nan', 'Unmatched')
步骤3:透视表生成目标列
将标识符转成列,填充% of capex的值,再合并回原df2:
# 生成透视表,每个identifier对应一列,值为% of capex pivot_df = merged_df.pivot_table( index=merged_df.index, # 保留原df2的索引,确保对齐 columns='identifier', values='% of capex', aggfunc='first' # 每个索引只取第一个值(因每个sic_code对应唯一的SDG+Direction) ) # 将新列合并回原df2 df2 = df2.join(pivot_df)
额外加速技巧
如果capex_sic_code在sic_tax中是唯一值,可以预先给sic_tax设置索引,进一步提升合并速度:
# 给sic_tax设置索引为capex_sic_code,加速关联 sic_tax = sic_tax.set_index('capex_sic_code') merged_df = df2[['capex_sic_code', '% of capex']].join( sic_tax[['SDG #', 'Direction (A, PA, PM, M)']], on='capex_sic_code' )
内容的提问来源于stack exchange,提问作者ZedIsDead
相关产品推荐
相关产品推荐

