Pandas百万级数据循环创建DataFrame行的性能优化方法
问题背景
现有基于pandas的多表关联构建数据集代码执行效率极低,处理1万行数据需耗时40分钟,无法支撑百万级数据处理需求。
当前实现代码:
def Data_Set_Creation(df1,df2,df3): d={"match_data":[], "unmatch_data":[]} for j in range(df3.shape[0]): d["match_data"].append(df1[df1.CORE_CUSTOMER_ID==df3.CORE_CUSTOMER_ID_1.to_list()[j]].reset_index()) d["unmatch_data"].append(df2[df2.CORE_CUSTOMER_ID==df3.CORE_CUSTOMER_ID_2.to_list()[j]].reset_index()) df1=pd.DataFrame(d["match_data"]) df2=pd.DataFrame(d["unmatch_data"]) df_prob_match=pd.concat([df1,df2],axis=1) return df_prob_match
业务逻辑说明:
- df1关联键为
CORE_CUSTOMER_ID,df2关联键为CORE_CUSTOMER_ID - df3存储所有待匹配的
CORE_CUSTOMER_ID_1、CORE_CUSTOMER_ID_2值对 - 输出要求:将df1中匹配到对应
CORE_CUSTOMER_ID_1的行、df2中匹配到对应CORE_CUSTOMER_ID_2的行横向拼接为同一行,得到完整匹配结果集
性能瓶颈分析
- 核心问题是使用Python层逐行循环遍历df3,属于pandas开发典型反模式,循环本身开销极高
- 每次循环都对df1、df2做全表扫描匹配,时间复杂度为O(n*(m+k))(n为df3行数,m、k分别为df1、df2行数),数据量增长时耗时呈指数级上升
- 每次循环重复调用
to_list()做全列转列表操作,存在大量无意义的重复计算 - 逐行append存储DataFrame片段,触发频繁的内存分配与拷贝,额外开销占比极高
优化实现方案
核心思路是用pandas内置的向量化merge操作替代逐行循环,所有匹配逻辑走底层C实现,时间复杂度降至线性级别,百万级数据处理通常仅需数秒到数十秒。
优化后代码:
import pandas as pd def Data_Set_Creation(df1: pd.DataFrame, df2: pd.DataFrame, df3: pd.DataFrame) -> pd.DataFrame: # 关联df1匹配CORE_CUSTOMER_ID_1对应的数据 match_df1 = pd.merge( left=df3, right=df1, left_on="CORE_CUSTOMER_ID_1", right_on="CORE_CUSTOMER_ID", how="left" ) # 关联df2匹配CORE_CUSTOMER_ID_2对应的数据,同名字段自动加后缀区分 final_result = pd.merge( left=match_df1, right=df2, left_on="CORE_CUSTOMER_ID_2", right_on="CORE_CUSTOMER_ID", how="left", suffixes=("_from_df1", "_from_df2") ) return final_result
进一步提速建议
针对百万级以上超大规模数据,可叠加以下优化手段:
- 关联前统一三个表关联键的数据类型(统一为整型或字符串),避免merge时的隐式类型转换开销
- 内存充足场景下,提前对df1、df2执行
df1 = df1.set_index("CORE_CUSTOMER_ID")、df2 = df2.set_index("CORE_CUSTOMER_ID")将关联键设为索引,改用join操作替代merge,速度可再提升30%以上 - 千万级以上数据量可替换为polars库实现相同逻辑,相比pandas速度可提升5-20倍,内存占用降低50%以上
- 关联前提前确认关联键是否存在一对多情况,若存在需提前按业务规则去重,避免笛卡尔积导致结果行数爆炸、内存溢出
内容的提问来源于stack exchange,提问作者rakesh.data
相关产品推荐
相关产品推荐

