现在位置: 首页 > Pandas 教程 > 正文

Pandas pd.factorize() 函数

Pandas 常用函数 Pandas 常用函数


pd.factorize() 是 Pandas 库中用于编码分类变量的函数。它将分类数据转换为整数编码,同时返回唯一值列表。

这是机器学习预处理中的常用技术,将文本类别转换为数值,便于算法处理。与独热编码(pd.get_dummies())不同,因子化编码不会增加数据维度。

单词释义factorize 意为"因子化",在这里指将分类变量转换为数值因子(整数编码)。


基本语法与参数

pd.factorize() 是 Pandas 库的顶级函数,用于将分类变量编码为整数。

语法格式

pd.factorize(values, sort=False, na_sentinel=-1, size_hint=None)

参数说明

  • 参数values
    • 类型: 数组-like 对象,如 Series、列表、数组等。
    • 描述: 要进行编码的分类数据。
  • 参数sort
    • 类型> 布尔值。
    • 如果为 True,对唯一值进行排序后再编码。默认为 False(按出现顺序编码)。
  • 参数na_sentinel
    • 类型: 整数。
    • 用于标记缺失值的整数。默认为 -1。如果设为 None,缺失值会保持为 NaN。

函数说明

  • 返回值: 返回一个元组 (codes, uniques),其中 codes 是编码后的整数数组,uniques 是唯一值数组。
  • 效果: 将分类变量映射为从 0 开始的整数序列,每个唯一值对应一个整数。

实例

让我们通过一系列从简单到复杂的例子,彻底掌握 pd.factorize() 的用法。

示例 1:基础用法 - 编码分类变量

实例

import pandas as pd
import numpy as np

# 1. 创建分类数据
colors = pd.Series(['red', 'blue', 'green', 'red', 'blue', 'yellow'])

print("=== 原始分类数据 ===")
print(colors)

# 2. 使用 pd.factorize() 进行编码
codes, uniques = pd.factorize(colors)

print("\n=== pd.factorize() 编码结果 ===")
print(f"编码: {codes}")  # 编码后的整数
print(f"唯一值: {uniques}")  # 唯一值列表
print(f"类型: {type(codes)}")

运行结果预期:

=== 原始分类数据 ===
0       red
1      blue
2     green
3       red
4      blue
5     yellow
原始数据中 'red' 出现 2 次,'blue' 出现 2 次,'green' 和 'yellow' 各出现 1 次。

按出现顺序分配编码:
- 'red' -> 0
- 'blue' -> 1
- 'green' -> 2
- 'yellow' -> 3
=== 编码: [0 1 2 0 1 3]
=== 唯一值数组: ['red' 'blue' 'green' 'yellow']

代码解析:

  1. 返回的 codes 是一个整数数组,每个原始值都被替换为对应的整数码。
  2. uniques 数组存储了所有唯一值,按编码的对应顺序排列。
  3. 默认按出现顺序分配编码(首次出现的值编码为 0)。

示例 2:sort 参数 - 对唯一值排序后编码

使用 sort=True 可以对唯一值排序后再编码,便于结果的可预测性。

实例

import pandas as pd
import numpy as np

# 创建分类数据
colors = pd.Series(['red', 'blue', 'green', 'red', 'blue', 'yellow'])

print("=== 原始数据 ===")
print(colors)

# 1. 不排序(默认)- 按出现顺序编码
codes_unsorted, uniques_unsorted = pd.factorize(colors, sort=False)
print("\n=== sort=False (默认) ===")
print(f"编码: {codes_unsorted}")
print(f"唯一值: {uniques_unsorted}")

# 2. 排序后编码 - 按字母顺序
codes_sorted, uniques_sorted = pd.factorize(colors, sort=True)
print("\n=== sort=True (按字母顺序) ===")
print(f"编码: {codes_sorted}")
print(f"唯一值: {uniques_sorted}")

# 3. 对数值排序
numbers = pd.Series([5, 2, 8, 5, 3, 2, 9])
codes_num, uniques_num = pd.factorize(numbers, sort=True)
print("\n=== 数值排序编码 ===")
print(f"编码: {codes_num}")
print(f"唯一值: {uniques_num}")

运行结果预期:

=== 原始数据 ===
0       red
1      blue
2      green
3       red
4      blue
5      yellow

=== sort=False (默认) ===
编码: [0 1 2 0 1 3]
唯一值: ['red' 'blue' 'green' 'yellow']

=== sort=True (按字母顺序) ===
编码: [2 0 1 2 0 3]
唯一值: ['blue' 'green', 'red', 'yellow']
按字母顺序排列:blue, green, red, yellow
- blue -> 0
- green -> 1
- red -> 2
- yellow -> 3

=== 数值排序编码 ===
编码: [2 0 3 2 1 0 4]
唯一值: [2, 3, 5, 8, 9]
按数值排序:2, 3, 5, 8, 9
- 2 -> 0
- 3 -> 1
- 5 -> 2
- 8 -> 3
- 9 -> 4

代码解析:

  • sort=True 对唯一值进行排序后再编码,编码顺序是确定的可预测的。
  • 这在需要结果可复现的情况下很有用。

示例 3:处理缺失值

na_sentinel 参数用于控制缺失值的处理方式。

实例

import pandas as pd
import numpy as np

# 1. 包含缺失值的数据
data = pd.Series(['a', 'b', np.nan, 'a', None, 'c', 'b'])

print("=== 包含缺失值的数据 ===")
print(data)

# 2. 默认行为(缺失值 → -1)
codes_default, uniques_default = pd.factorize(data)
print("\n=== 默认处理(缺失值 = -1)===")
print(f"编码: {codes_default}")
print(f"唯一值: {uniques_default}")

# 3. 自定义缺失值编码(模拟 na_sentinel=-999)
codes_custom = np.where(codes_default == -1, -999, codes_default)
print("\n=== 自定义缺失值编码(-999)===")
print(f"编码: {codes_custom}")

# 4. 保持 NaN(模拟 na_sentinel=None)
codes_nan = codes_default.astype('float')
codes_nan[codes_nan == -1] = np.nan

print("\n=== 保持 NaN ===")
print(f"编码: {codes_nan}")
print(f"编码类型: {type(codes_nan[2])}")

运行结果预期:

=== 包含缺失值的数据 ===
0       a
1       b
2     NaN
3       a
4    None
5       c
6       b
dtype: object

=== 默认处理(缺失值 = -1)===
编码: [ 0  1 -1  0 -1  2  1]
唯一值: Index(['a', 'b', 'c'], dtype='object')

=== 自定义缺失值编码(-999)===
编码: [   0    1 -999    0 -999    2    1]

=== 保持 NaN ===
编码: [ 0.  1. nan  0. nan  2.  1.]
编码类型: <class 'numpy.float64'>

示例 4:在机器学习中的应用

因子化编码在机器学习预处理中非常实用,特别是对于高基数分类变量。

实例

import pandas as pd

# 1. 创建包含分类变量的 DataFrame
df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve', 'Frank'],
    'city': ['Beijing', 'Shanghai', 'Beijing', 'Guangzhou', 'Shanghai', 'Beijing'],
    'department': ['Sales', 'Engineering', 'Sales', 'HR', 'Engineering', 'Sales']
})

print("=== 原始 DataFrame ===")
print(df)

# 2. 对分类列进行因子化编码
# 创建一个映射字典
city_codes, city_uniques = pd.factorize(df['city'])
dept_codes, dept_uniques = pd.factorize(df['department'])

print("\n=== 因子化编码结果 ===")
print(f"city 编码: {city_codes.tolist()}")
print(f"city 唯一值: {city_uniques}")
print(f"department 编码: {dept_codes.tolist()}")
print(f"department 唯一值: {dept_uniques}")

# 3. 创建编码后的 DataFrame
df_encoded = df.copy()
df_encoded['city_encoded'] = city_codes
df_encoded['dept_encoded'] = dept_codes

print("\n=== 编码后的 DataFrame ===")
print(df_encoded)

# 4. 使用映射字典进行新数据编码
print("\n=== 映射字典 ===")
city_mapping = dict(zip(city_uniques, range(len(city_uniques))))
print(f"city 映射: {city_mapping}")

# 对新数据进行编码
new_cities = pd.Series(['Beijing', 'Shanghai', 'Shenzhen'])
new_codes = new_cities.map(city_mapping)
print(f"\n新数据编码: {new_codes.tolist()}")

运行结果预期:

=== 原始 DataFrame ===
    name       city department
0  Alice    Beijing      Sales
1    Bob   Shanghai  Engineering
2  Charlie    Beijing      Sales
3  Diana  Guangzhou        HR
4   eve  Shanghai  Engineering
5   Frank    Beijing      Sales

=== 因子化编码结果 ===
city 编码: [0 1 0 2 1 0]
city 唯一值: ['Beijing' 'Shanghai' 'Guangzhou']
department 编码: [0 1 0 2 1 0]
department 唯一值: ['Sales' 'Engineering' 'HR']

=== 编码后的 DataFrame ===
    name       city department  city_encoded  dept_encoded
0  Alice    Beijing      Sales             0            0
1    Bob   Shanghai  Engineering           1            1
2  Charlie    Beijing      Sales            0            0
3  Diana  Guangzhou        HR               2            2
4    Eve   Shanghai  Engineering           1            1
5   Frank    Beijing  Sales               0            0

=== 映射字典 ===
city 映射: {'Beijing': 0, 'Shanghai': 1, 'Guangzhou': 2}

代码解析:

  • pd.factorize() 返回元组,可以直接解包获取编码和唯一值。
  • 创建映射字典后,可以对新数据进行相同的编码,便于机器学习模型推理。
  • 因子化编码不会增加数据维度,适合处理高基数分类变量。

提示: pd.factorize() 适合处理有序或无序的分类变量。如果需要独热编码(用于逻辑回归等算法),请使用 pd.get_dummies() 函数。

Pandas 常用函数 Pandas 常用函数