You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

astype("category")、categorical()与factorize()的区别及应用解析

Pandas分类变量转换方法对比:factorize()、Categorical()与astype("category")

Python里把变量转成分类变量有好几种方式,先看基础示例:

import numpy as np
import pandas as pd

mydata = pd.Series(['A', 'B', 'B', 'C'])

# 原始数据
print(mydata)
# 输出:
# 0    A
# 1    B
# 2    B
# 3    C
# dtype: object

# pd.factorize 输出包含编码数组和类别索引的元组
print(pd.factorize(mydata))
# 输出:(array([0, 1, 1, 2], dtype=int64), Index(['A', 'B', 'C'], dtype='object'))

# pd.Categorical 生成分类对象
cat_obj = pd.Categorical(mydata)
print(cat_obj)
# 输出:
# ['A', 'B', 'B', 'C']
# Categories (3, object): ['A', 'B', 'C']
# 提取类别:cat_obj.categories

# astype('category') 将Series转为分类类型
cat_series = mydata.astype('category')
print(cat_series)
# 输出:
# 0    A
# 1    B
# 2    B
# 3    C
# dtype: category
# Categories (3, object): ['A', 'B', 'C']
# 提取类别:cat_series.cat.categories

一、三种方法的核心区别

  • pd.factorize():本质是标签编码工具,返回整数编码数组+对应原始类别的索引元组。它不改变原数据类型,只是给每个唯一类别分配整数ID,更偏向于纯数值映射。
  • pd.Categorical():生成独立的分类数据对象,是pandas专门的分类容器,但不属于Series/DataFrame结构,单独存储类别和对应数据。
  • astype("category"):直接将原Series转为Categorical类型的Series,在原数据结构基础上修改类型,保留Series的所有操作方法。

二、优劣势对比

1. pd.factorize()

  • 优势:
    • 轻量快速,直接生成整数编码,适合模型需要纯数值输入的场景
    • 支持任意可哈希类型,不局限于字符串类别
    • 结果是元组,能直接提取编码和类别映射关系
  • 劣势:
    • 不保留分类数据的特殊属性(比如类别顺序、空类别),只是简单编码
    • 生成的是普通数组,无法使用pandas分类类型的专属操作(如.cat下的方法)

2. pd.Categorical()

  • 优势:
    • 纯粹的分类容器,适合单独处理分类逻辑
    • 可自定义类别顺序、提前指定未出现的类别(比如枚举所有可能的取值)
    • 内存占用比原始object类型小,类别重复越多优势越明显
  • 劣势:
    • 不属于Series结构,无法直接和其他pandas数据无缝结合,需转成Series才能参与分析
    • 操作不如astype转换后的分类Series直观

3. astype("category")

  • 优势:
    • 直接转换原Series,完全保留Series的所有操作(如.groupby()、.value_counts()),无缝融入日常分析流程
    • 内存效率高,自带分类类型的所有特性(类别管理、顺序控制)
    • 代码简洁直观,是日常数据清洗的首选
  • 劣势:
    • 无法直接获取整数编码,需额外调用.cat.codes提取
    • 默认基于当前数据的唯一值生成类别,自定义类别需额外传参

三、适用场景选择

1. 决策树等模型输入

优先选pd.factorize():模型需要整数编码时,它一步返回整数数组,还能直接拿到类别映射方便后续解释模型;如果后续还要做特征工程,也可以先转成分类Series,再提取编码。

2. 生成频率表/统计分析

优先选astype("category"):转换后的分类Series可以直接用.value_counts()、.groupby()等方法,自动识别类别,包括自定义的未出现类别,统计更准确。

3. 提前定义固定类别(比如枚举值)

用**pd.Categorical()或astype("category")**加categories参数:

# 提前定义所有可能的类别,即使当前数据里没有
pd.Categorical(mydata, categories=['A', 'B', 'C', 'D'])
mydata.astype('category', categories=['A', 'B', 'C', 'D'])

这种场景下pd.factorize()不适用,因为它只会基于当前数据生成类别。

四、后续类别修改的易用性

如果需要修改类别、添加新类别、更改值或合并类别,astype("category")生成的分类Series最易用,其次是pd.Categorical(),pd.factorize()几乎无法直接操作:

  • 添加新类别:分类Series可以用.cat.add_categories():
    cat_series = cat_series.cat.add_categories('D')
    
  • 合并类别:用.cat.rename_categories()或.cat.set_categories():
    # 合并A和B为AB
    cat_series = cat_series.cat.rename_categories({'A':'AB', 'B':'AB'})
    
  • 修改类别顺序:用.cat.reorder_categories()

pd.Categorical()可以调用同样的.cat方法,但需要先转成Series才能方便结合其他数据;而pd.factorize()生成的是普通数组,修改类别只能重新编码,非常麻烦。

另外补充:sklearn的LabelEncoder、keras的to_categorical属于机器学习专用工具,适合在流水线中保存转换规则,方便后续对新数据做相同编码,而pandas的三种方法更偏向数据清洗和分析阶段的处理。

内容的提问来源于stack exchange,提问作者skan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 21:45:15