内存占用降90%因categorical用整数编码+类别列表替代原始字符串存储;适合唯一值少、离散重复高、不参与数值计算的列;需注意nan处理、大小写清洗及有序分类慎用。

内存占用为什么能降90%?
因为 Categorical 不存原始字符串,而是用整数编码(codes)+ 唯一类别列表(categories)的结构存储。比如一列 100 万行的 ['男', '女', '男', '女', ...],原本每行都存两个 Unicode 字符(约 8 字节 × 100 万 = 8MB),改用 Categorical 后只存 100 万个 int8 编码(1 字节 × 100 万 = 1MB)+ 2 个字符串(['男', '女'],共约几百字节)——总内存直接压到原来的 1/8 左右。
哪些列适合转成 Categorical?
不是所有字符串列都值得转。关键看三点:
- 唯一值数量远小于总行数(例如 100 万行中只有 5 个不同值)
- 值是离散、有限、重复高的(如
['北京', '上海', '广州', '深圳'],不是['用户_123456789', '用户_123456790', ...]) - 不参与数值计算(
Categorical不能做+、mean()等,但支持value_counts()、groupby()、isin()
用 df[col].nunique() / len(df) 快速估算“唯一值占比”,低于 5% 就很适合。
astype('category') 的坑:缺失值和后续操作
直接写 df['col'] = df['col'].astype('category') 看似简单,但要注意:
- 如果原列含
NaN,转换后NaN会保留,但属于“未定义类别”,cat.categories里看不到它 - 用
query()或loc筛选时,NaN行默认被排除(行为和object列一致),但容易误以为是数据丢了 - 后续若想做 one-hot 编码,
pd.get_dummies(df['col'])会自动跳过NaN,不用额外处理 - 如果列里混有空格、大小写不一致(如
'Male'和'male'),先str.strip().str.lower()再转,否则会多出冗余类别
有序分类(ordered=True)什么时候必须用?
仅当你需要按业务逻辑排序,且该顺序**不等于字母序或数字序**时才启用。例如:
-
['低', '中', '高']→ 想让sort_values()按此顺序排,而不是按字符 'gao' > 'di' > 'zhong' -
['S', 'A', 'B', 'C'](游戏段位)→ 不能靠字符串比较得出正确高低
一旦设为 ordered=True,就不能再用 cat.rename_categories() 改变顺序,只能重建 CategoricalDtype。所以别随便开这个开关。
astype('category') ——这反而增加内存,因为每个唯一值都要进 categories 列表,还多存一套整数索引。判断前先跑一遍 nunique(),比凭感觉靠谱得多。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











