大体积pandas dataframe内存优化及CSV导出效率提升咨询
带空值整数列的内存优化及CSV写入方案
核心背景说明
你当前看到的带空值的int64列本质上已经是float64类型——因为原生numpy的int64不支持存储空值,pandas遇到空值会自动将整列类型提升为float64,这部分是内存浪费的核心来源。以下是可落地的优化方案:
方案1:切换到Pandas专属可空整数类型(优先级最高)
- 适用场景:所有原本为整数、因含空值被转为
float64的列,空值占比任意 - 优化效果:内存占用直接降低为原
float64类型的1/2~1/8,同时避免整数序列化为CSV时出现.0后缀,大幅降低写入时的字符串序列化开销 - 代码示例:
import pandas as pd import numpy as np def get_optimal_nullable_int_dtype(series): # 过滤空值后计算取值范围 non_na_vals = series.dropna() min_val = non_na_vals.min() max_val = non_na_vals.max() # 匹配位数最小的可空整数类型(首字母大写为Pandas专属可空类型) if min_val >= -128 and max_val <= 127: return "Int8" elif min_val >= -32768 and max_val <= 32767: return "Int16" elif min_val >= -2147483648 and max_val <= 2147483647: return "Int32" else: return "Int64" # 筛选出符合条件的候选列:float64类型、非空值均为整数 int_candidate_cols = [] for col in df.select_dtypes(include=["float64"]).columns: non_na = df[col].dropna() if len(non_na) == 0: continue # 兼容浮点数精度误差判断是否为整数 if np.all(np.isclose(non_na % 1, 0)): int_candidate_cols.append(col) # 批量转换为最优可空整数类型 for col in int_candidate_cols: opt_dtype = get_optimal_nullable_int_dtype(df[col]) df[col] = df[col].astype(opt_dtype)
方案2:高空值占比列改用稀疏类型
- 适用场景:单列空值占比超过70%的场景,空值占比越高优化效果越好
- 优化效果:仅存储非空值的位置和数值,空值不占用存储空间,空值占比90%的列内存降幅可达90%以上
- 代码示例:
# 计算所有列的空值占比 na_ratio = df.isna().sum() / len(df) # 筛选空值占比>70%的整数列 sparse_candidates = na_ratio[na_ratio > 0.7].index.intersection(int_candidate_cols) # 转换为稀疏可空整数类型 for col in sparse_candidates: df[col] = df[col].astype(pd.SparseDtype(dtype=df[col].dtype, fill_value=np.nan))
CSV写入效率&体积优化
完成上述类型转换后,CSV写入的序列化成本已经大幅降低,配合以下参数可进一步提升效率、减小文件体积:
df.to_csv( "output.csv.gz", index=False, na_rep="", # 空值统一存储为空字符串,避免冗余字符,适配数仓场景可改为'\N' compression="gzip", # 直接输出gzip压缩格式,写入速度与普通CSV接近,体积仅为未压缩的10%~20% engine="c", # 启用C语言引擎写入,速度是Python引擎的2倍以上 chunksize=1000000 # 分块写入,避免1900万行数据一次性刷入内存导致OOM )
如果你的使用场景允许替换输出格式,改用parquet列式存储格式会比CSV有数量级的性能和体积优势,但如果必须输出CSV,上述参数已经是最优配置。
内容的提问来源于stack exchange,提问作者Bsleon
相关产品推荐
相关产品推荐

