Pandas - Categorical 数据类型带来的效率和作用
描述
- 在遇到量大且重复的数据时,将其某 Series 转换为
Categorical
类型,再结合groupby
函处理数据效率会更高。 - 给 Series 打上标记,标注排列顺序,结合
sort_values
函数将DataFrame
进行重新排序。
自定义排序
Categorical
可以按照特定的顺序进行排序。在定义 Categorical
类型时,你可以指定一个类别的顺序,这被称为类别的有序性(orderliness)。如果你没有指定顺序,类别将按照它们在数据中出现的顺序进行排序。
要按照特定顺序排序 Categorical
数据,你需要在创建 Categorical
类型的时候指定 categories
参数来定义顺序,并设置 ordered=True
来表示这个顺序是有意义的。
file:[例1]
import pandas as pd
cat_type = pd.CategoricalDtype(categories=['low', 'medium', 'high'], ordered=True)
ser = pd.Series(['low', 'medium', 'high', 'medium', 'low'], dtype=cat_type, name='quality')
df = pd.DataFrame(ser).sort_values(by=['quality'])
打印结果:
file:[打印结果2]
quality
0 low
4 low
1 medium
3 medium
2 high
结合 groupby
例如,假设你有一个包含商品信息的 DataFrame
,并且其中有一列是商品类型,类型的数量相对于数据集是有限的。首先,你可以将商品类型列转换为 Categorical
类型:
file:[例2]
import pandas as pd
df = pd.DataFrame({
'product_type': ['apple', 'banana', 'cherry', 'apple'],
'price': [12, 13, 14, 12.5]
})
df['product_type'] = df['product_type'].astype('category')
average_price_per_type = df.groupby('product_type', observed=True)['price'].mean()
由于数据量少,似乎加不加 Categorical
类型都不影响。打印结果:
file:[打印结果1]
product_type
apple 12.25
banana 13.00
cherry 14.00
Name: price, dtype: float64
学习 Categorical
通过以上案例对该数据类型有了一个初步的了解,现在将系统性地进行学习。
Categorical
是给 Series 数据打上标记的一种数据类型,例如,一个调查问卷的答案(非常同意、同意、中立、不同意、非常不同意),就有5种标记。
给 Series 打上标记之后,不影响原有的数据内容,如下代码所示:
file:[例3]
cat_type = pd.CategoricalDtype(categories=['low', 'medium', 'high'], ordered=True)
ser = pd.Series(['low', 'medium', 'high', 'medium', 'low'], dtype=cat_type, name='quality')
"""打印结果
0 low
1 medium
2 high
3 medium
4 low
Name: quality, dtype: category
Categories (3, object): ['low' < 'medium' < 'high']
"""
Series 创建
dtype
file:[例4]
ser = pd.Series(["a", "b", "c", "a"], dtype="category")
"""打印结果
0 a
1 b
2 c
3 a
dtype: category
Categories (3, object): ['a', 'b', 'c']
"""
可以直接给 dtype 传递 CategoricalDtype 类型描述构建,如例3中所示。
astype
file:[例5]
df = pd.DataFrame({"A": ["a", "b", "c", "a"]})
df["B"] = df["A"].astype("category")
"""打印结果
A B
0 a a
1 b b
2 c c
3 a a
"""
可以直接给 astype 传递 CategoricalDtype 类型描述构建,如例3中所示。
Categorical 构造器
file:[例6]
raw_cat = pd.Categorical(
["a", "b", "c", "a"], categories=["b", "c", "d"], ordered=False
)
ser = pd.Series(raw_cat)
"""打印结果
0 NaN
1 b
2 c
3 NaN
dtype: category
Categories (3, object): ['b', 'c', 'd']
"""
DataFrame 创建
dtype
file:[例7]
df = pd.DataFrame({"A": list("abca"), "B": list("bccd")}, dtype="category")
"""df.dtypes 打印结果
A category
B category
dtype: object
"""
"""df 打印结果
A B
0 a b
1 b c
2 c c
3 a d
"""
可以直接给 dtype 传递 CategoricalDtype 类型描述构建,如例3中所示。
astype
file:[例8]
df = pd.DataFrame({"A": list("abca"), "B": list("bccd")})
df_cat = df.astype("category")
可以直接给 astype 传递 CategoricalDtype 类型描述构建,如例3中所示。
Categorical 构造器
file:[例9]
dfs = pd.DataFrame(
{
"A": pd.Categorical(
list("bbeebbaa"),
categories=["e", "a", "b"],
ordered=True,
),
"B": [1, 2, 1, 2, 2, 1, 2, 1],
}
)
set_categories 和 reorder_categories
设置 category 排序规则。
file:[例10]
s = pd.Series(["one", "two", "-", "four"], dtype="category")
print(s.cat.reorder_categories(['one', 'two', 'four', '-', 'three']).sort_values(ascending=False), '\n')
"""报错
ValueError: items in new_categories are not the same as in old categories
"""
s = pd.Series(["one", "two", "-", "four"], dtype="category")
print(s.cat.reorder_categories(['one', 'two', 'four', '-']).sort_values(ascending=False), '\n')
"""
2 -
3 four
1 two
0 one
dtype: category
Categories (4, object): ['one', 'two', 'four', '-']
"""
如上例10示,reorder_categories
在 Series 中没有的就会报错,而 set_categories
则不会,没有的也会设置上。