二、有序分类

1. 序的建立

有序类别和无序类别可以通过 as_unorderedreorder_categories 互相转化,需要注意的是后者传入的参数必须是由当前序列的无序类别构成的列表,不能够增加新的类别,也不能缺少原来的类别,并且必须指定参数 ordered=True ,否则方法无效。例如,对年级高低进行相对大小的类别划分,然后再恢复无序状态:

In [22]: s = df.Grade.astype('category')
In [23]: s = s.cat.reorder_categories(['Freshman', 'Sophomore',
   ....:                               'Junior', 'Senior'],ordered=True)
   ....: 
In [24]: s.head()
Out[24]: 
0     Freshman
1     Freshman
2       Senior
3    Sophomore
4    Sophomore
Name: Grade, dtype: category
Categories (4, object): ['Freshman' < 'Sophomore' < 'Junior' < 'Senior']
In [25]: s.cat.as_unordered().head()
Out[25]: 
0     Freshman
1     Freshman
2       Senior
3    Sophomore
4    Sophomore
Name: Grade, dtype: category
Categories (4, object): ['Freshman', 'Sophomore', 'Junior', 'Senior']

类别不得直接修改

如果不想指定 ordered=True 参数,那么可以先用 s.cat.as_ordered() 转化为有序类别,再利用 reorder_categories 进行具体的相对大小调整。

2. 排序和比较

第二章 pandas基础 中,曾提到了字符串和数值类型序列的排序,此时就要说明分类变量的排序:只需把列的类型修改为 category 后,再赋予相应的大小关系,就能正常地使用 sort_indexsort_values 。例如,对年级进行排序:

In [26]: df.Grade = df.Grade.astype('category')
In [27]: df.Grade = df.Grade.cat.reorder_categories(['Freshman',
   ....:                                             'Sophomore',
   ....:                                             'Junior',
   ....:                                             'Senior'],ordered=True)
   ....: 
In [28]: df.sort_values('Grade').head() # 值排序
Out[28]: 
        Grade           Name  Gender  Height  Weight
0    Freshman   Gaopeng Yang  Female   158.9    46.0
105  Freshman      Qiang Shi  Female   164.5    52.0
96   Freshman  Changmei Feng  Female   163.8    56.0
88   Freshman   Xiaopeng Han  Female   164.1    53.0
81   Freshman    Yanli Zhang  Female   165.1    52.0
In [29]: df.set_index('Grade').sort_index().head() # 索引排序
Out[29]: 
                   Name  Gender  Height  Weight
Grade                                  
Freshman   Gaopeng Yang  Female   158.9    46.0
Freshman      Qiang Shi  Female   164.5    52.0
Freshman  Changmei Feng  Female   163.8    56.0
Freshman   Xiaopeng Han  Female   164.1    53.0
Freshman    Yanli Zhang  Female   165.1    52.0

由于序的建立,因此就可以进行比较操作。分类变量的比较操作分为两类,第一种是 ==!= 关系的比较,比较的对象可以是标量或者同长度的 Series (或 list ),第二种是 >,>=,<,<= 四类大小关系的比较,比较的对象和第一种类似,但是所有参与比较的元素必须属于原序列的 categories ,同时要和原序列具有相同的索引。

In [30]: res1 = df.Grade == 'Sophomore'
In [31]: res1.head()
Out[31]: 
0    False
1    False
2    False
3     True
4     True
Name: Grade, dtype: bool
In [32]: res2 = df.Grade == ['PhD']*df.shape[0]
In [33]: res2.head()
Out[33]: 
0    False
1    False
2    False
3    False
4    False
Name: Grade, dtype: bool
In [34]: res3 = df.Grade <= 'Sophomore'
In [35]: res3.head()
Out[35]: 
0     True
1     True
2    False
3     True
4     True
Name: Grade, dtype: bool
In [36]: res4 = df.Grade <= df.Grade.sample(
   ....:                             frac=1).reset_index(
   ....:                                       drop=True) # 打乱后比较
   ....: 
In [37]: res4.head()
Out[37]: 
0     True
1     True
2    False
3     True
4     True
Name: Grade, dtype: bool