category类型能省内存,但仅适用于唯一值占比低于50%的低基数字符串列,如性别、省份等,可省60%–90%内存;高基数列反而增加开销。
能省,但不是所有字符串列都适合。关键看「唯一值数量 / 总行数」是否明显小于 0.5(即重复度高)。比如性别、省份、订单状态这类低基数(low-cardinality)列,转 category 后内存常减少 60%–90%;而用户昵称、日志消息这种几乎每行都不同的列,转了反而多一层索引开销。
str.contains()) 用这行快速检查:
df['col'].nunique() / len(df)
df.info() 的 memory usage —— 它默认不 deep,得加 deep=True 才算真实字符串内存。
因为底层存的是整数编码(0, 1, 2…),排序实际是对整数数组操作,比逐个比较字符串快 3–5 倍。但注意:默认排序按「类别出现顺序」或「字典序」,不是你业务里的逻辑顺序(比如 “高” > “中” > “低”)。
CategoricalDtype:from pandas.api.types import CategoricalDtype
cat_type = CategoricalDtype(categories=['低', '中', '高'], ordered=True)
df['level'] = df['level'].astype(cat_type)
df['level'].astype('category') 不带 ordered=True,后续 sort_values() 会按字典序排,且无法做大小比较(df['level'] > '中' 报错) sort_
values() 对已设 ordered=True 的列,自动按定义顺序升序;降序就加 ascending=False,无需额外映射等 pd.read_csv() 把整列读成 object 再转 category,中间已占用大量内存。应该在读取时直接指定 dtype:
dtype 参数:df = pd.read_csv('data.csv', dtype={'status': 'category', 'region': 'category'}) dtype={'user_id': 'uint32', 'score': 'float32'} convert_dtypes() 做兜底(但它不会自动把字符串转 category,只转为 string 类型)漏掉这步,100 万行含 3 个高重复字符串列的数据,可能多占 200MB+ 内存,且后续所有 groupby、sort_values 都更慢。
category 列 categories 不一致(比如左有 ['A','B'],右有 ['B','C']),结果列会自动转回 object,内存和性能优势瞬间消失 df[df['cat_col'] == 'X'] 没问题,但用 isin() 要小心:df[df['cat_col'].isin(['X','Y'])] 若 'Y' 不在 categories 中,会静默返回空 —— 不报错,但结果不对 真正省内存,靠的不是“转一次”,而是从读入、处理到输出全程保持类型意识。一个列转了 category,不代表它就永远安全了——任何隐式类型推断操作(比如 pd.concat()、merge()、甚至某些 apply())都可能把它悄悄打回原形。