Category节省内存靠去重+整数编码,非压缩;它用一个短列表存唯一值、一个整数数组存索引,避免重复存储字符串对象;唯一率超5%时反而更占内存。

为什么 object 列转 category 能省内存?
因为 object 类型在 pandas 中对每个字符串都存一份独立副本(指针+实际字符串对象),而 category 只存唯一值列表(categories)和一个整数编码数组(codes)。当列中重复值多(比如国家名、状态码、产品分类),内存可降 50%–90%。
但注意:如果每行值几乎都不同(如 UUID、长随机文本),转 category 反而更占内存——因为要额外存索引映射表。
用 astype("category") 转换的实操要点
最直接的方式是调用 astype("category"),但它默认把所有唯一值都纳入 categories,不筛选也不排序。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 若原始列含大量
NaN,astype("category")会保留它们,且NaN在codes中统一记为-1,不影响内存节省 - 想控制类别顺序(比如让 "low" pd.Categorical 构造再赋值,不能只靠
astype - 转换后列的 dtype 显示为
category,但.values返回的是pd.Categorical对象,不是 numpy 数组;要用.array.codes或.cat.codes拿整数编码
df["status"] = df["status"].astype("category")
pd.Categorical 手动构造更可控
当你需要显式指定 categories、处理缺失值逻辑、或复用同一套分类体系时,绕过 astype 直接用 pd.Categorical 更稳妥。
立即学习“Python免费学习笔记(深入)”;
- 传入
categories参数可强制限定合法取值,超出范围的值会变NaN(除非设ordered=True且用fastpath=False) - 设
ordered=True后,该列支持<、sort_values()等序关系操作,但会略微增加元数据开销 - 如果原始列是
object但含混合类型(比如字符串混着数字),pd.Categorical会报TypeError,必须先清洗
df["grade"] = pd.Categorical(df["grade"], categories=["F", "D", "C", "B", "A"], ordered=True)
转完别忘检查真实内存变化
很多人以为调了 astype("category") 就一定省内存,其实不一定——尤其当列本身就很短,或 pandas 版本较老(
- 用
df.memory_usage(deep=True).sum()对比前后总内存,比只看单列.nbytes准确 - 如果列含大量未使用的空字符串
""或空白符,先.str.strip().replace("", np.nan)再转 category,效果更好 - 保存为
parquet时,category 列会被高效编码;但存成csv会退化回字符串,白省了
真正省不省,跑一遍 memory_usage 最实在。别凭感觉,也别信“只要转就省”。

















