为何Pandas中列转category时dtype不同且存在两种行为差异?
Pandas中object/str转category时dtype差异的深层原因
嘿,这个问题其实戳中了Pandas category类型的核心细节,我来一步步给你拆解清楚:
1. 为何从object或str类型转换为category时,dtype会有所不同?
首先得明确:Pandas的category类型是个「复合类型」,它由两部分组成:
- categories:存储所有唯一的类别值的集合
- codes:存储每个元素对应的类别索引(始终是整数类型,比如int8、int16,会根据类别数量自动选择最节省空间的类型)
你感觉到的「dtype不同」,本质是categories的底层数据类型不一样,而非category类型本身有差异:
- 当你从「str类型列」(注意:Pandas没有原生str dtype,这类列实际是
objectdtype,只是所有元素都是字符串)转category时,categories会保留字符串类型,所以查看series.cat.categories.dtype会得到object(这是Pandas存储字符串的默认方式)。 - 当你从「object类型列」转category时,如果这个object列里的元素是整数(比如原本是int列,后来转成了object),那么
categories会直接沿用整数类型(比如int64),这就造成了和str转category时的dtype差异。
2. 为何转换时会出现两种不同行为?
咱们用代码示例直观展示你说的场景,顺便解释原因:
import pandas as pd # 场景1:int列→object→category df1 = pd.DataFrame({'col': [1, 2, 3, 1, 2]}) df1['col'] = df1['col'].astype(object) # 此时列是object dtype,但元素是int64 cat_col1 = df1['col'].astype('category') print(cat_col1.cat.categories.dtype) # 输出:int64 # 场景2:int列→str(本质还是object)→category df2 = pd.DataFrame({'col': [1, 2, 3, 1, 2]}) df2['col'] = df2['col'].astype(str) # 此时列是object dtype,元素是str cat_col2 = df2['col'].astype('category') print(cat_col2.cat.categories.dtype) # 输出:object
出现这种差异的核心逻辑很简单:
Pandas在将object列转换为category时,会完全保留原object列中元素的底层数据类型来构建categories集合:
- 场景1里,object列的元素是整数,所以categories的dtype就是int64;
- 场景2里,object列的元素是字符串,所以categories的dtype就是object(Pandas存储字符串的标准方式)。
而codes部分不管原类型是什么,都是整数类型——Pandas会自动选最节省空间的整数 dtype(比如类别数少于256时用int8,更多的话升级到int16等)。
小提示
如果希望统一转换后的categories dtype,你可以在转category前先标准化列的元素类型,比如统一转成字符串:
df1['col'] = df1['col'].astype(str).astype('category') print(df1['col'].cat.categories.dtype) # 输出:object
内容的提问来源于stack exchange,提问作者J. Leroux
相关产品推荐
相关产品推荐

