Pandas空值处理:多列滤空单列留空的内存最优方案
内存高效处理百万级CSV文件的方案
嘿,这个需求我日常处理大文件时经常遇到,给你一套经过验证的低内存实现思路,全程尽量避免加载冗余数据,一步步来:
1. 只加载需要的6列,从源头减少内存占用
首先别加载全部15列,用pd.read_csv的usecols参数直接指定要保留的6列名称,这是最直接的内存节省手段——毕竟不需要的数据读进来纯浪费内存。
示例代码:
import pandas as pd # 替换成你实际需要保留的6列名称 target_cols = ['col_a', 'col_b', 'col_c', 'col_d', 'col_e', 'col_f']
2. 提前指定最优数据类型,避免默认推断的内存浪费
Pandas默认的类型推断经常会把小范围数值列当成int64/float64,把枚举型文本列当成object,这会大幅增加内存占用。我们可以先采样一小部分数据,确定每列的最优类型:
步骤2.1 采样获取类型信息
# 只读前1000行来推断类型 sample_df = pd.read_csv('your_large_file.csv', usecols=target_cols, nrows=1000) # 查看当前类型 print(sample_df.dtypes) # 手动指定更优类型,比如: # - 枚举类文本列用category # - 数值列用最小能容纳范围的类型(比如int8/int16,float32) dtype_spec = { 'col_a': 'category', # 如果是枚举值 'col_b': 'int16', # 如果数值范围在-32768到32767之间 'col_c': 'float32', 'col_d': 'category', 'col_e': 'int8', 'col_f': 'object' # 这列是要保留空值的列,按需指定 }
3. 分块读取+逐块处理,避免一次性加载全量数据
百万级文件如果一次性加载到内存,即使只留6列也可能占用几GB内存。用chunksize参数分块读取,每次处理一小部分数据(比如1万行),内存占用控制在单块的大小:
核心处理逻辑:筛选符合条件的行
我们需要的行满足:5列无空值,同时剩下1列是空值。假设col_f是要保留空值的列,其他5列是需要过滤空值的列,那么筛选条件就是:
# 5列全部非空 且 col_f为空 filter_condition = (df[target_cols[:-1]].notna().all(axis=1)) & (df['col_f'].isna())
分块处理+写入结果(内存最优方式)
不要把所有结果存在内存里再合并,而是处理一块就写入一块到输出文件,这样内存占用最低:
# 输出文件路径 output_file = 'filtered_result.csv' # 第一次写入时加表头,后续块不加 first_chunk = True # 分块读取,chunksize可根据你的内存情况调整(比如10000、20000) for chunk in pd.read_csv( 'your_large_file.csv', usecols=target_cols, dtype=dtype_spec, chunksize=10000, na_values=['', 'NaN', 'NULL'] # 统一识别各种空值形式 ): # 筛选符合条件的行 filtered_chunk = chunk[ (chunk[['col_a', 'col_b', 'col_c', 'col_d', 'col_e']].notna().all(axis=1)) & (chunk['col_f'].isna()) ] # 写入结果 filtered_chunk.to_csv( output_file, mode='a', # 追加模式 header=first_chunk, index=False ) # 之后的块不再写表头 first_chunk = False
额外优化点
- 如果你的文件是用特定分隔符,记得指定
sep参数,避免Pandas自动推断浪费时间和内存。 - 如果不需要索引,读取和写入时都加
index=False,减少不必要的内存开销。 - 对于特别大的文件,可以考虑用
dask.dataframe替代Pandas,它是并行处理大文件的工具,内存占用更低,但学习成本稍高——如果上面的方案足够用,就没必要折腾。
内容的提问来源于stack exchange,提问作者TJE
相关产品推荐
相关产品推荐

