DataFrame列转categorical后内存激增?原因及优化方案咨询
为什么转成Categorical后内存反而变大?
核心原因有这几个:
- 唯一值占比过高:Categorical的优势是把重复字符串映射成整数索引来省内存,但如果列里唯一值数量接近总行数(比如45K行里某列有40K个唯一值),存储整数索引的开销加上唯一值字典的开销,会远大于原来object类型存储字符串指针的开销(64位系统下每个object元素是8字节指针)。
- NaN的额外开销:默认情况下,Categorical会把NaN当作单独类别存储,每列的NaN都会占用类别字典空间,多列大量NaN叠加后,内存开销会很明显。
- 转换方式未优化:手动用全列唯一值字典转Categorical时,可能没指定最小整数存储类型(比如默认用int64存索引,但唯一值少的话用int8/int16就够),额外浪费了内存。
降低DataFrame内存占用的实用步骤
- 先评估每列唯一值占比:运行
df.nunique() / len(df),只给唯一值占比低于20%(可按需调整)的列转Categorical,占比高的列别转,反而浪费内存。 - 优化Categorical存储:直接用
df[col] = df[col].astype('category'),pandas会自动选择最小的整数类型存储类别索引,比手动字典转换更高效;不需要排序的话保持ordered=False(默认值),避免额外排序开销。 - 改用StringDtype处理字符串列:如果pandas版本在1.0以上,对字符串列用
df[col] = df[col].astype('string'),它是Nullable字符串类型,比object更省内存,唯一值多的场景下比Categorical更合适,还能原生处理NaN。 - 优化数值列类型:如果数值型数据存在object列里,先用
pd.to_numeric(df[col], errors='coerce')转成数值类型,再用df[col] = pd.to_numeric(df[col], downcast='integer')(或'float')自动降级到最小可用数值类型,比如把int64降到int16。 - 分块处理大数据:如果DataFrame超出内存承载,用
pd.read_csv(chunksize=10000)(或其他读取函数的chunksize参数)分块读取处理,处理完一块释放一块内存。 - 清理冗余数据:删掉不需要的列、重复行,用
df.drop(columns=['无用列'])和df.drop_duplicates(),减少内存占用的基础操作。
内容的提问来源于stack exchange,提问作者Eduardo EPF
相关产品推荐
相关产品推荐

