基于Python&Pandas优化大批量DataFrame处理及容错的技术咨询
批量生成DataFrame的存储与筛选优化问题
背景情况
- 现有Python脚本需生成50000个指定结构的DataFrame,最初逐个保存到本地磁盘;将存储格式从Excel改为Parquet后,运行效率未得到提升。
- 后续需要遍历这些DataFrame,筛选出
Meet列值为4或5的行,最终保存为TXT文件。 - 考虑在生成每个小DataFrame时直接筛选目标行,跳过逐个存储小文件的步骤,直接写入最终文件,但不确定百万级行数能否在**Win11(16GB内存、无网络)**的普通笔记本上运行。
- 当前尝试将筛选后的小DataFrame存入列表,合并后导出为Excel,但曾因意外断电导致需重跑整个流程,寻求更优解决方案。
DataFrame结构示例
Dict DT Length Meet 0 {'key_0': 45, 'key_1': 67} 2023-10-15 14:32:10 15 5 1 {'key_0': 12, 'key_1': 34} 2023-10-12 09:15:45 19 3 2 {'key_0': 56, 'key_1': 89} 2023-10-20 11:45:30 13 7 3 {'key_0': 23, 'key_1': 45} 2023-10-05 08:20:00 17 4 4 {'key_0': 78, 'key_1': 12} 2023-10-10 16:05:55 10 6
当前尝试的代码片段
big_df = [] # --- 生成df_small的代码 --- df_small = df_small[df_small['Meet'].isin([4,5])] big_df.append(df_1) # 注:此处应为df_small,疑似笔误 writing_df = pd.concat(big_df, ignore_index=True) writing_df.to_excel('final.xlsx', index=False)
优化方案
方案1:逐批筛选后直接追加写入TXT文件
无需将所有筛选后的数据存入内存,每生成并筛选一个小DataFrame,就直接追加写入最终TXT文件,既节省内存,又能避免断电重跑的问题(已写入的内容不会丢失)。
示例代码:
# 先创建文件并写入表头(仅执行一次) header = ['Dict', 'DT', 'Length', 'Meet'] with open('final_result.txt', 'w', encoding='utf-8') as f: f.write('\t'.join(header) + '\n') # 循环生成每个小DataFrame并处理 for _ in range(50000): # --- 生成df_small的代码 --- df_small = df_small[df_small['Meet'].isin([4,5])] # 将筛选后的数据追加写入TXT,用制表符分隔 df_small.to_csv('final_result.txt', mode='a', header=False, index=False, sep='\t', encoding='utf-8')
方案2:分阶段保存中间结果+合并筛选
如果担心直接写入TXT的灵活性不足,可以将筛选后的小DataFrame以Parquet格式分批次保存(比如每1000个小DataFrame合并成一个Parquet文件),这样即使断电,只需要重跑未完成的批次,无需从头开始。
示例代码:
batch_size = 1000 batch_count = 0 temp_dfs = [] for i in range(50000): # --- 生成df_small的代码 --- df_small = df_small[df_small['Meet'].isin([4,5])] temp_dfs.append(df_small) # 每积累batch_size个小DataFrame,合并保存为一个Parquet文件 if (i + 1) % batch_size == 0: batch_count += 1 batch_df = pd.concat(temp_dfs, ignore_index=True) batch_df.to_parquet(f'filtered_batch_{batch_count}.parquet', index=False) temp_dfs = [] # 清空列表释放内存 # 处理剩余不足一个批次的数据 if temp_dfs: batch_count += 1 batch_df = pd.concat(temp_dfs, ignore_index=True) batch_df.to_parquet(f'filtered_batch_{batch_count}.parquet', index=False) # 最后合并所有批次的Parquet文件并导出为TXT import glob parquet_files = glob.glob('filtered_batch_*.parquet') final_df = pd.concat([pd.read_parquet(f) for f in parquet_files], ignore_index=True) final_df.to_csv('final_result.txt', index=False, sep='\t', encoding='utf-8') # 可选:删除临时Parquet文件 import os for f in parquet_files: os.remove(f)
方案可行性说明
- 对于16GB内存的Win11笔记本,方案1完全可行:每次仅处理单个小DataFrame,内存占用极低,百万级行数的TXT文件写入也不会有压力。
- 方案2的内存压力也可控,因为每个批次仅合并1000个筛选后的小DataFrame,内存占用远低于一次性合并50000个的情况。
内容的提问来源于stack exchange,提问作者Mark K
相关产品推荐
相关产品推荐

