Polars中Categorical与Enum类型内存占用及优化、转换问题问询
Polars分类/Enum列内存占用问题解答
内存大小是否准确?
准确。Polars的Categorical和Enum列默认使用int32类型存储类别索引,不管实际类别数量多少,底层数组的类型都是int32,因此estimated_size()返回的内存占用和同长度int32列一致。shrink_to_fit()仅用于清理类别字典中的冗余条目,不会改变底层索引的整数类型,所以无法降低内存占用。
三个疑问的解答
1. 能否减少成员数量少的分类类型的内存占用?
可以。你可以在创建Categorical/Enum列时,指定更小的整数类型作为索引存储类型:
- 对于Categorical列,创建时通过
dtype参数指定更小的无符号整数类型,比如类别数≤255用pl.UInt8,≤65535用pl.UInt16:# 示例:将整数列转为用UInt8存储索引的Categorical df = df.with_columns(pl.col("cat_col").cast(pl.Categorical(dtype=pl.UInt8))) - Enum列同样支持该参数,因为Polars的Enum是基于Categorical实现的:
# 示例:创建基于UInt8的Enum列 MyEnum = pl.Enum(["a", "b", "c", "d"], dtype=pl.UInt8) df = df.with_columns(pl.col("enum_col").cast(MyEnum))
2. 有无更优方法将整数ID转换为分类类型?
直接将整数ID转为Categorical/Enum即可,无需额外处理。如果整数ID的范围很小,指定对应小整数类型的Categorical是最优方案,既避免了字符串转换的开销,又能最大化节省内存:
# 直接转换整数列为小索引类型的Categorical df = df.with_columns(pl.col("int_id").cast(pl.Categorical(dtype=pl.UInt8)))
如果整数ID对应的是固定枚举值,也可以直接定义Enum类型后转换,类型安全性更高:
StatusEnum = pl.Enum([0, 1, 2, 3], dtype=pl.UInt8) df = df.with_columns(pl.col("status").cast(StatusEnum))
3. 是否需先转换为字符串?
不需要。直接转换整数ID为Categorical/Enum是更高效的方式:
- 内存上:不用存储字符串,仅存储小整数索引,内存占用远低于字符串列。
- 性能上:避免了字符串解析、哈希等额外开销,转换和后续操作速度更快。
只有当你的类别逻辑依赖字符串标识(比如需要将整数ID映射为对应的字符串名称)时,才需要先将整数转为字符串再处理。
内容的提问来源于stack exchange,提问作者user1441053
相关产品推荐
相关产品推荐

