处理大型CSV文件的内存优化代码故障排查请求
问题排查与修正方案
一、原代码核心问题分析
内存计算函数
f_Size逻辑错误
原函数通过计算每种数据类型的内存均值再累加,完全不符合内存统计逻辑——正确做法是统计每种类型列的总内存后累加,均值累加无法反映真实内存占用,导致你看不到优化前后的差异。数值类型转换逻辑冗余且错误
在f_Zip函数中,循环每个列时又嵌套循环所有int/float类型,重复对全表同类型列做转换,不仅效率低,还可能导致转换后的列无法正确覆盖到优化后的DataFrame中。Object转Category的赋值错误
原代码中xOptimize_File[xFile[xCol]] = xConverted_Object是错误的索引方式,应该直接使用列名xCol来赋值。无符号整数转换的风险
使用downcast="unsigned"会把所有整数转成无符号类型,但如果列中存在负数,会导致数据错误,应该根据列的数值范围选择合适的转换方式。
二、修正后的完整代码
import numpy as np import pandas as pd import tkinter as tk from tkinter import filedialog xInt_Types = ["int64", "int32", "int16", "int8", "uint64", "uint32", "uint16", "uint8"] xFloat_Types = ["float64", "float32", "float16"] # 选择CSV文件 xPath = filedialog.askopenfilename() xFile = pd.read_csv(xPath) xColumnName = xFile.columns # 正确计算DataFrame的总内存占用(单位:MB) def f_Size(xDataFrame): total_bytes = xDataFrame.memory_usage(deep=True).sum() return total_bytes / (1024 ** 2) # 查看数值类型的范围信息 def f_Info(xInt_Types, xFloat_Types): for xInt in xInt_Types: print(np.iinfo(xInt)) for xFlt in xFloat_Types: print(np.finfo(xFlt)) # 计算DataFrame或单列的内存占用(单位:字节) def f_M_U(xPandas_Data): return xPandas_Data.memory_usage(deep=True).sum() if isinstance(xPandas_Data, pd.DataFrame) else xPandas_Data.memory_usage(deep=True) # 查看所有Object类型列的统计信息 def f_CSV_Attr(xFile): xFile_Object = xFile.select_dtypes(include=["object"]) if not xFile_Object.empty: print(xFile_Object.describe()) # 内存优化核心函数 def f_Zip(xFile): xOptimize_File = xFile.copy() for xCol in xOptimize_File.columns: dtype = xOptimize_File[xCol].dtype # 整数类型优化 if dtype in xInt_Types: # 判断是否有负数,选择有符号/无符号向下转换 if xOptimize_File[xCol].min() >= 0: xOptimize_File[xCol] = pd.to_numeric(xOptimize_File[xCol], downcast="unsigned") else: xOptimize_File[xCol] = pd.to_numeric(xOptimize_File[xCol], downcast="integer") # 浮点类型优化 elif dtype in xFloat_Types: xOptimize_File[xCol] = pd.to_numeric(xOptimize_File[xCol], downcast="float") # Object类型转Category(唯一值占比<50%时) elif dtype == "object": num_unique = len(xOptimize_File[xCol].unique()) num_total = len(xOptimize_File[xCol]) if num_unique / num_total < 0.5: xOptimize_File[xCol] = xOptimize_File[xCol].astype("category") return xOptimize_File # 输出优化前后的内存占用 print('原始文件内存占用(MB):', round(f_Size(xFile), 4)) xOptimize_File = f_Zip(xFile) print('优化后文件内存占用(MB):', round(f_Size(xOptimize_File), 4))
三、关键修正说明
修复内存计算逻辑
f_Size函数改为直接统计所有列的内存总和,再转换为MB,能准确反映真实内存占用。简化数值类型转换
针对每个列单独处理,根据列的数值范围选择有符号/无符号整数转换,避免重复循环和全表处理,提升效率。修复Category赋值错误
直接使用列名xCol赋值,确保转换后的Category类型列正确替换原列。优化Object列统计函数
f_CSV_Attr改为只统计一次所有Object列,避免重复输出。
内容的提问来源于stack exchange,提问作者Pino
相关产品推荐
相关产品推荐

