Pandas 分类数据(Categorical Data)处理全面指南
1. 引言
分类数据(Categorical Data)是数据分析中常见的数据类型,它表示有限且通常固定的可能值集合。Pandas 提供了专门的分类数据类型(categorical dtype)来高效处理这类数据。本文将详细介绍分类变量的概念、创建方法以及各种操作函数,并通过实际代码示例展示如何使用它们。
2. 分类数据简介
2.1 什么是分类数据
分类数据是指具有有限且固定数量可能值的数据,通常分为:
- 有序分类:有明确的顺序关系(如:小、中、大)
- 无序分类:没有顺序关系(如:红、绿、蓝)
2.2 为什么使用分类数据类型
使用分类数据类型的主要优势:
- 内存效率:只存储唯一类别一次,其余存储为引用
- 性能提升:对分类数据的操作更快
- 语义清晰:明确表示数据的分类性质
3. 创建分类数据
3.1 从列表/数组创建
python
import pandas as pd
# 从列表创建分类Series
categories = pd.Series(['a', 'b', 'c', 'a', 'b'], dtype='category')
print("基本分类数据:\n", categories)
输出:
基本分类数据:
0 a
1 b
2 c
3 a
4 b
dtype: category
Categories (3, object): ['a', 'b', 'c']
3.2 使用Categorical构造函数
python
from pandas.api.types import CategoricalDtype
# 使用Categorical构造函数
cat = pd.Categorical(['a', 'b', 'c', 'a', 'b'], categories=['a', 'b', 'c', 'd'])
print("\n使用Categorical创建:\n", cat)
解释:
- 可以预先指定所有可能的类别,即使某些类别未出现
d
类别被包含但未使用
3.3 指定有序分类
python
# 创建有序分类
ordered_cat = pd.Categorical(['low', 'high', 'medium', 'low'],
categories=['low', 'medium', 'high'],
ordered=True)
print("\n有序分类:\n", ordered_cat)
4. 分类数据基本属性
4.1 查看类别
python
# 查看类别
print("\n类别:", categories.cat.categories)
# 查看是否有序
print("是否有序:", categories.cat.ordered)
4.2 重命名类别
python
# 重命名类别
categories = categories.cat.rename_categories(['A', 'B', 'C'])
print("\n重命名后:\n", categories)
5. 分类数据操作
5.1 添加新类别
python
# 添加新类别
categories = categories.cat.add_categories(['d'])
print("\n添加类别后:\n", categories.cat.categories)
5.2 删除未使用类别
python
# 删除未使用类别
categories = categories.cat.remove_unused_categories()
print("\n删除未使用类别后:\n", categories.cat.categories)
5.3 设置类别顺序
python
# 设置类别顺序
categories = categories.cat.set_categories(['C', 'B', 'A', 'd'], ordered=True)
print("\n设置顺序后:\n", categories)
6. 分类数据排序
6.1 按类别顺序排序
python
# 创建示例DataFrame
df = pd.DataFrame({
'grade': pd.Categorical(['B', 'A', 'C', 'B'],
categories=['A', 'B', 'C'],
ordered=True),
'value': [2, 1, 3, 4]
})
# 按分类列排序
sorted_df = df.sort_values('grade')
print("\n按分类排序:\n", sorted_df)
6.2 自定义排序顺序
python
# 自定义排序顺序
custom_order = pd.CategoricalDtype(['C', 'B', 'A'], ordered=True)
df['grade'] = df['grade'].astype(custom_order)
print("\n自定义顺序排序:\n", df.sort_values('grade'))
7. 分类数据分组
7.1 分组统计
python
# 分组统计
grouped = df.groupby('grade').mean()
print("\n分组统计:\n", grouped)
7.2 显示所有类别分组
python
# 显示所有类别分组(即使空组)
grouped = df.groupby('grade', observed=False).mean()
print("\n包含空组的分组:\n", grouped)
8. 分类数据与虚拟变量
8.1 转换为虚拟变量
python
# 转换为虚拟变量
dummies = pd.get_dummies(df['grade'], prefix='grade')
print("\n虚拟变量:\n", dummies)
8.2 从虚拟变量转换回分类
python
# 从虚拟变量转换回分类
from_dummies = pd.from_dummies(dummies, sep='_')
print("\n从虚拟变量转换:\n", from_dummies)
9. 分类数据的内存使用
9.1 比较内存使用
python
# 创建大型数据集
large_series = pd.Series(['a', 'b', 'c'] * 10000)
# 比较内存使用
print("\n对象类型内存使用:", large_series.memory_usage())
print("分类类型内存使用:", large_series.astype('category').memory_usage())
10. 分类数据的性能优势
10.1 比较操作性能
python
import timeit
# 创建测试数据
cat_series = pd.Series(['a', 'b', 'c'] * 10000).astype('category')
str_series = pd.Series(['a', 'b', 'c'] * 10000)
# 测试groupby性能
def groupby_cat():
return cat_series.groupby(cat_series).count()
def groupby_str():
return str_series.groupby(str_series).count()
print("\n分类数据groupby时间:", timeit.timeit(groupby_cat, number=100))
print("字符串数据groupby时间:", timeit.timeit(groupby_str, number=100))
11. 实际应用案例
11.1 处理调查数据
python
# 调查数据处理示例
survey_data = pd.DataFrame({
'response_id': range(1, 6),
'age_group': ['18-25', '26-35', '18-25', '36-50', '26-35'],
'satisfaction': ['Very Satisfied', 'Neutral', 'Satisfied', 'Very Satisfied', 'Dissatisfied']
})
# 转换为分类数据
age_cat = pd.CategoricalDtype(['18-25', '26-35', '36-50', '51+'], ordered=True)
sat_cat = pd.CategoricalDtype(['Very Satisfied', 'Satisfied', 'Neutral', 'Dissatisfied'],
ordered=True)
survey_data['age_group'] = survey_data['age_group'].astype(age_cat)
survey_data['satisfaction'] = survey_data['satisfaction'].astype(sat_cat)
# 交叉分析
cross_tab = pd.crosstab(survey_data['age_group'],
survey_data['satisfaction'],
dropna=False)
print("\n调查数据交叉表:\n", cross_tab)
12. 总结
-
分类数据基础:
- 分类数据表示有限且固定的可能值集合
- 分为有序分类和无序分类两种类型
-
创建分类数据:
- 可以通过
dtype='category'
直接创建 - 使用
pd.Categorical
构造函数提供更多控制 - 可以指定类别顺序创建有序分类
- 可以通过
-
分类数据操作:
- 查看和修改类别:
categories
,rename_categories
- 管理类别:
add_categories
,remove_categories
,remove_unused_categories
- 设置顺序:
set_categories
,as_ordered
,as_unordered
- 查看和修改类别:
-
排序与分组:
- 分类数据保持定义的顺序进行排序
- 分组操作可以利用分类信息提高效率
-
内存与性能:
- 分类数据通常比字符串类型更节省内存
- 对分类数据的操作(如groupby)通常更快
-
实际应用:
- 非常适合处理调查数据、固定选项数据
- 可以生成更有意义的交叉表和统计结果
使用分类数据类型的最佳实践:
- 当变量有固定数量的可能值时使用
- 当变量的值有自然顺序时指定为有序分类
- 对于大型数据集,分类类型可以显著提高性能
掌握Pandas的分类数据处理功能可以帮助你更高效地处理和分析具有固定类别的数据,同时节省内存并提高性能。