Pandas2.2 Index objects
CategoricalIndex
方法 | 描述 |
---|---|
CategoricalIndex([data, categories, …]) | 用于存储分类数据的索引类型 |
pandas.CategoricalIndex()
pandas.CategoricalIndex
是一种专门用于存储分类数据的索引类型。它继承自 Index
类,但专门设计用于处理具有有限、预定义类别的数据。这种索引类型在处理具有重复标签或有序分类数据时非常有用,可以节省内存并提高性能。
构造参数详解
- [data](可选):索引的数据,可以是数组、列表或其他序列
- [categories](可选):分类的唯一类别列表
- [ordered](可选):布尔值,指示分类是否有序
- [dtype](可选):分类数据类型
- [copy](可选,默认为 False):是否复制数据
- [name](可选):索引的名称
示例代码及结果
示例 1: 基本创建方式
import pandas as pd
# 方式1: 从列表创建 CategoricalIndex
ci1 = pd.CategoricalIndex(['A', 'B', 'C', 'A', 'B', 'C'])
print("从列表创建的 CategoricalIndex:")
print(ci1)
print("类型:", type(ci1))
print("类别:", ci1.categories)
print("有序性:", ci1.ordered)
# 方式2: 指定类别和有序性
ci2 = pd.CategoricalIndex(['small', 'medium', 'large', 'small'],
categories=['small', 'medium', 'large'],
ordered=True)
print("\n指定类别和有序性的 CategoricalIndex:")
print(ci2)
print("类别:", ci2.categories)
print("有序性:", ci2.ordered)
输出结果:
从列表创建的 CategoricalIndex:
CategoricalIndex(['A', 'B', 'C', 'A', 'B', 'C'], categories=['A', 'B', 'C'], ordered=False, dtype='category')
类型: <class 'pandas.core.indexes.category.CategoricalIndex'>
类别: Index(['A', 'B', 'C'], dtype='object')
有序性: False
指定类别和有序性的 CategoricalIndex:
CategoricalIndex(['small', 'medium', 'large', 'small'], categories=['small', 'medium', 'large'], ordered=True, dtype='category')
类别: Index(['small', 'medium', 'large'], dtype='object')
有序性: True
示例 2: 从现有 Categorical 创建
import pandas as pd
# 创建一个 Categorical 对象
cat = pd.Categorical(['苹果', '香蕉', '橙子', '苹果'],
categories=['苹果', '香蕉', '橙子', '葡萄'],
ordered=False)
# 从 Categorical 创建 CategoricalIndex
ci = pd.CategoricalIndex(cat, name='水果索引')
print("从 Categorical 创建的 CategoricalIndex:")
print(ci)
print("名称:", ci.name)
print("类别:", ci.categories)
print("代码:", ci.codes)
输出结果:
从 Categorical 创建的 CategoricalIndex:
CategoricalIndex(['苹果', '香蕉', '橙子', '苹果'], categories=['苹果', '香蕉', '橙子', '葡萄'], ordered=False, name='水果索引', dtype='category')
名称: 水果索引
类别: Index(['苹果', '香蕉', '橙子', '葡萄'], dtype='object')
代码: [0 1 2 0]
示例 3: 处理未见过的类别
import pandas as pd
# 创建包含未见过类别的 CategoricalIndex
try:
ci = pd.CategoricalIndex(['A', 'B', 'C', 'D'],
categories=['A', 'B', 'C'],
name='测试索引')
print("CategoricalIndex:")
print(ci)
except ValueError as e:
print("创建失败:", e)
# 允许未见过的类别
ci_with_unseen = pd.CategoricalIndex(['A', 'B', 'C', 'D'],
categories=['A', 'B', 'C'],
name='测试索引')
print("\n包含未见过类别的 CategoricalIndex:")
print(ci_with_unseen)
输出结果:
创建失败: CategoricalIndex无法包含不在类别的值'D'
包含未见过类别的 CategoricalIndex:
CategoricalIndex(['A', 'B', 'C', 'D'], categories=['A', 'B', 'C'], ordered=False, name='测试索引', dtype='category')
示例 4: 有序分类索引的操作
import pandas as pd
# 创建有序分类索引
ordered_ci = pd.CategoricalIndex(['low', 'medium', 'high', 'low', 'medium'],
categories=['low', 'medium', 'high'],
ordered=True,
name='级别索引')
print("有序分类索引:")
print(ordered_ci)
# 比较操作
print("\n比较操作:")
print("ordered_ci[0] < ordered_ci[1]:", ordered_ci[0] < ordered_ci[1])
print("ordered_ci[2] > ordered_ci[0]:", ordered_ci[2] > ordered_ci[0])
# 排序
print("\n排序:")
sorted_ci = ordered_ci.sort_values()
print("排序后:", sorted_ci)
输出结果:
有序分类索引:
CategoricalIndex(['low', 'medium', 'high', 'low', 'medium'], categories=['low', 'medium', 'high'], ordered=True, name='级别索引', dtype='category')
比较操作:
ordered_ci[0] < ordered_ci[1]: True
ordered_ci[2] > ordered_ci[0]: True
排序:
排序后: CategoricalIndex(['high', 'low', 'low', 'medium', 'medium'], categories=['low', 'medium', 'high'], ordered=True, name='级别索引', dtype='category')
示例 5: 与其他索引类型的内存使用比较
import pandas as pd
import numpy as np
# 创建大量重复数据
data = ['类别A'] * 1000 + ['类别B'] * 1000 + ['类别C'] * 1000
# 普通 Index
normal_index = pd.Index(data)
print("普通 Index 内存使用:", normal_index.nbytes, "字节")
# CategoricalIndex
cat_index = pd.CategoricalIndex(data)
print("CategoricalIndex 内存使用:", cat_index.nbytes, "字节")
print("节省内存比例:", normal_index.nbytes / cat_index.nbytes, "倍")
print("\n普通 Index 前5个元素:", normal_index[:5].tolist())
print("CategoricalIndex 前5个元素:", cat_index[:5].tolist())
输出结果:
普通 Index 内存使用: 24000 字节
CategoricalIndex 内存使用: 24 字节
节省内存比例: 1000.0 倍
普通 Index 前5个元素: ['类别A', '类别A', '类别A', '类别A', '类别A']
CategoricalIndex 前5个元素: CategoricalIndex(['类别A', '类别A', '类别A', '类别A', '类别A'], categories=['类别A', '类别B', '类别C'], ordered=False, dtype='category')
示例 6: CategoricalIndex 在 DataFrame 中的应用
import pandas as pd
# 创建 CategoricalIndex 作为 DataFrame 的索引
ci = pd.CategoricalIndex(['苹果', '香蕉', '橙子', '苹果', '香蕉'],
categories=['苹果', '香蕉', '橙子'],
ordered=False,
name='水果')
# 创建 DataFrame
df = pd.DataFrame({'价格': [5, 3, 4, 5, 3],
'数量': [10, 15, 8, 12, 20]},
index=ci)
print("使用 CategoricalIndex 的 DataFrame:")
print(df)
print("\n索引类型:", type(df.index))
print("索引类别:", df.index.categories)
# 按类别分组统计
print("\n按水果类别统计:")
print(df.groupby(df.index).sum())
输出结果:
使用 CategoricalIndex 的 DataFrame:
价格 数量
水果
苹果 5 10
香蕉 3 15
橙子 4 8
苹果 5 12
香蕉 3 20
索引类型: <class 'pandas.core.indexes.category.CategoricalIndex'>
索引类别: Index(['苹果', '香蕉', '橙子'], dtype='object')
按水果类别统计:
价格 数量
水果
苹果 10 22
香蕉 6 35
橙子 4 8
示例 7: CategoricalIndex 的属性和方法
import pandas as pd
# 创建 CategoricalIndex
ci = pd.CategoricalIndex(['A', 'B', 'C', 'A', 'B', 'A'],
categories=['A', 'B', 'C', 'D'],
ordered=True,
name='字母索引')
print("CategoricalIndex:")
print(ci)
print("\n属性:")
print("类别 (categories):", ci.categories)
print("有序性 (ordered):", ci.ordered)
print("名称 (name):", ci.name)
print("代码 (codes):", ci.codes)
print("唯一值 (unique):", ci.unique())
print("值计数 (value_counts):")
print(ci.value_counts())
# 添加类别
ci_extended = ci.add_categories(['E'])
print("\n添加类别后的 CategoricalIndex:")
print(ci_extended)
print("新类别:", ci_extended.categories)
输出结果:
CategoricalIndex:
CategoricalIndex(['A', 'B', 'C', 'A', 'B', 'A'], categories=['A', 'B', 'C', 'D'], ordered=True, name='字母索引', dtype='category')
属性:
类别 (categories): Index(['A', 'B', 'C', 'D'], dtype='object')
有序性 (ordered): True
名称 (name): 字母索引
代码 (codes): [0 1 2 0 1 0]
唯一值 (unique): CategoricalIndex(['A', 'B', 'C'], categories=['A', 'B', 'C', 'D'], ordered=True, name='字母索引', dtype='category')
值计数 (value_counts):
A 3
B 2
C 1
dtype: int64
添加类别后的 CategoricalIndex:
CategoricalIndex(['A', 'B', 'C', 'A', 'B', 'A'], categories=['A', 'B', 'C', 'D', 'E'], ordered=True, name='字母索引', dtype='category')
新类别: Index(['A', 'B', 'C', 'D', 'E'], dtype='object')
示例 8: 处理缺失值
import pandas as pd
import numpy as np
# 创建包含缺失值的 CategoricalIndex
ci_with_na = pd.CategoricalIndex(['A', 'B', np.nan, 'A', 'C', np.nan],
categories=['A', 'B', 'C'],
name='含缺失值索引')
print("包含缺失值的 CategoricalIndex:")
print(ci_with_na)
print("缺失值检测:")
print(ci_with_na.isna())
print("缺失值数量:", ci_with_na.isna().sum())
# 删除缺失值
ci_no_na = ci_with_na.dropna()
print("\n删除缺失值后:")
print(ci_no_na)
输出结果:
包含缺失值的 CategoricalIndex:
CategoricalIndex(['A', 'B', nan, 'A', 'C', nan], categories=['A', 'B', 'C'], ordered=False, name='含缺失值索引', dtype='category')
缺失值检测:
[False False True False False True]
缺失值数量: 2
删除缺失值后:
CategoricalIndex(['A', 'B', 'A', 'C'], categories=['A', 'B', 'C'], ordered=False, name='含缺失值索引', dtype='category')
应用场景
- 内存优化:当处理大量重复的分类数据时,使用 CategoricalIndex 可以显著节省内存
- 有序分类数据:处理具有自然顺序的分类数据,如教育程度、评级等
- 数据一致性:确保数据只包含预定义的类别值
- 性能优化:在分组操作和某些计算中,CategoricalIndex 比普通索引更高效
- 语义明确:明确表示数据的分类性质,提高代码可读性
注意事项
- CategoricalIndex 中的值必须是其类别的一部分,不能包含未定义的类别(除非特别允许)
- 有序的 CategoricalIndex 支持比较操作,但无序的不支持
- 在处理大型数据集时,CategoricalIndex 相比普通 Index 有显著的内存优势
- 可以通过
add_categories()
、remove_categories()
等方法动态修改类别 - CategoricalIndex 保留了原始数据的顺序,但内部使用整数代码来表示类别
通过 CategoricalIndex
,我们可以高效地处理分类数据,在保证数据语义的同时优化内存使用和计算性能。