一、cat对象

In [1]: import numpy as np
In [2]: import pandas as pd

1. cat对象的属性

pandas 中提供了 category 类型,使用户能够处理分类类型的变量,将一个普通序列转换成分类变量可以使用 astype 方法。

In [3]: df = pd.read_csv('data/learn_pandas.csv',
   ...:      usecols = ['Grade', 'Name', 'Gender', 'Height', 'Weight'])
   ...: 
In [4]: s = df.Grade.astype('category')
In [5]: s.head()
Out[5]: 
0     Freshman
1     Freshman
2       Senior
3    Sophomore
4    Sophomore
Name: Grade, dtype: category
Categories (4, object): ['Freshman', 'Junior', 'Senior', 'Sophomore']

在一个分类类型的 Series 中定义了 cat 对象,它和上一章中介绍的 str 对象类似,定义了一些属性和方法来进行分类类别的操作。

In [6]: s.cat
Out[6]: <pandas.core.arrays.categorical.CategoricalAccessor object at 0x0000026403481608>

对于一个具体的分类,有两个组成部分,其一为类别的本身,它以 Index 类型存储,其二为是否有序,它们都可以通过 cat 的属性被访问:

In [7]: s.cat.categories
Out[7]: Index(['Freshman', 'Junior', 'Senior', 'Sophomore'], dtype='object')
In [8]: s.cat.ordered
Out[8]: False

另外,每一个序列的类别会被赋予唯一的整数编号,它们的编号取决于 cat.categories 中的顺序,该属性可以通过 codes 访问:

In [9]: s.cat.codes.head()
Out[9]: 
0    0
1    0
2    2
3    3
4    3
dtype: int8

2. 类别的增加、删除和修改

通过 cat 对象的 categories 属性能够完成对类别的查询,那么应该如何进行“增改查删”的其他三个操作呢?

类别不得直接修改

第三章 中曾提到,索引 Index 类型是无法用 index_obj[0] = item 来修改的,而 categories 被存储在 Index 中,因此 pandascat 属性上定义了若干方法来达到相同的目的。

首先,对于类别的增加可以使用 add_categories

In [10]: s = s.cat.add_categories('Graduate') # 增加一个毕业生类别
In [11]: s.cat.categories
Out[11]: Index(['Freshman', 'Junior', 'Senior', 'Sophomore', 'Graduate'], dtype='object')

若要删除某一个类别可以使用 remove_categories ,同时所有原来序列中的该类会被设置为缺失。例如,删除大一的类别:

In [12]: s = s.cat.remove_categories('Freshman')
In [13]: s.cat.categories
Out[13]: Index(['Junior', 'Senior', 'Sophomore', 'Graduate'], dtype='object')
In [14]: s.head()
Out[14]: 
0          NaN
1          NaN
2       Senior
3    Sophomore
4    Sophomore
Name: Grade, dtype: category
Categories (4, object): ['Junior', 'Senior', 'Sophomore', 'Graduate']

此外可以使用 set_categories 直接设置序列的新类别,原来的类别中如果存在元素不属于新类别,那么会被设置为缺失。

In [15]: s = s.cat.set_categories(['Sophomore','PhD']) # 新类别为大二学生和博士
In [16]: s.cat.categories
Out[16]: Index(['Sophomore', 'PhD'], dtype='object')
In [17]: s.head()
Out[17]: 
0          NaN
1          NaN
2          NaN
3    Sophomore
4    Sophomore
Name: Grade, dtype: category
Categories (2, object): ['Sophomore', 'PhD']

如果想要删除未出现在序列中的类别,可以使用 remove_unused_categories 来实现:

In [18]: s = s.cat.remove_unused_categories() # 移除了未出现的博士生类别
In [19]: s.cat.categories
Out[19]: Index(['Sophomore'], dtype='object')

最后,“增改查删”中还剩下修改的操作,这可以通过 rename_categories 方法完成,同时需要注意的是,这个方法会对原序列的对应值也进行相应修改。例如,现在把 Sophomore 改成中文的 本科二年级学生

In [20]: s = s.cat.rename_categories({'Sophomore':'本科二年级学生'})
In [21]: s.head()
Out[21]: 
0        NaN
1        NaN
2        NaN
3    本科二年级学生
4    本科二年级学生
Name: Grade, dtype: category
Categories (1, object): ['本科二年级学生']