如何优化2600万行CSV数据的循环拼接效率?
高效重构大规模DataFrame的方案
原方法的性能瓶颈分析
你当前的代码存在两个核心性能问题:
iterrows()会逐行将DataFrame转换为Series,Python循环处理2600万行数据本身效率极低;- 每次循环调用
pd.concat()都会创建新的小DataFrame并复制已有数据,时间复杂度为O(n²),数据量越大,耗时呈指数级增长。
最优解决方案:用pd.wide_to_long实现向量化转换
你的需求本质是宽表转长表(将每行中对应4种Occupancy的权重列展开为多行),pandas内置的wide_to_long函数专门处理这类场景,完全避免Python循环,通过C级别的向量化操作完成转换,性能提升几个数量级。
具体代码实现
import pandas as pd # 假设原DataFrame dd的索引为Geoid,先将索引转为列 dd = dd.reset_index().rename(columns={'index': 'Geoid'}) # 使用wide_to_long将宽表转长表 n_df = pd.wide_to_long( dd, stubnames=['STR_WT', 'CNT_WT', 'BI_WT'], # 权重列的公共前缀部分 i='Geoid', # 作为标识的主键列 j='Occupancy', # 要展开的分类列(对应SFD/MFD/COM/IND) sep='_', # 列名中前缀与后缀的分隔符 suffix=r'\w+' # 匹配后缀的正则表达式 ).reset_index() # 重命名列以匹配目标格式 n_df = n_df.rename(columns={ 'STR_WT': 'BDG_Weights', 'CNT_WT': 'CTS_Weights', 'BI_WT': 'BI_Weights' })
替代方案:使用pd.melt(适配列名格式差异场景)
如果原列名格式存在细微差异,也可以用melt结合字符串处理实现:
# 重置索引为Geoid列 dd = dd.reset_index().rename(columns={'index': 'Geoid'}) # 先将所有权重列转为长格式 melted = dd.melt( id_vars=['Geoid'], var_name='Type_Weight', value_name='Value' ) # 拆分Type_Weight列,分离出Occupancy和权重类型 melted[['Occupancy', 'Weight_Type']] = melted['Type_Weight'].str.split('_', n=1, expand=True) # 重新透视回宽表,得到目标格式 n_df = melted.pivot( index=['Geoid', 'Occupancy'], columns='Weight_Type', values='Value' ).reset_index().rename(columns={ 'STR_WT': 'BDG_Weights', 'CNT_WT': 'CTS_Weights', 'BI_WT': 'BI_Weights' })
效果对比
- 原方法:处理2600万行数据需数小时,内存占用持续飙升;
- 优化后方法:基于向量化操作,处理相同数据量仅需几分钟,内存使用更可控。
内容的提问来源于stack exchange,提问作者Satya Dalei
相关产品推荐
相关产品推荐

