pandas处理分类数据
1.创建分类数据
分类数据指按一定区间,将数据分类,类似于数据分桶。
指定列数据类型:dtype=“category”,这样新建的series就是分类类型。
pd.Series(["a", "b", "c", "a"], dtype="category")
0 a
1 b
2 c
3 a
dtype: category
Categories (3, object): [a, b, c]
pandas有内置类,可以直接创建
利用内置Categorical类型创建
cat = pd.Categorical(["a", "b", "c", "a"], categories=['a','b','c'])
pd.Series(cat)
Out[4]:
0 a
1 b
2 c
3 a
dtype: category
Categories (3, object): [a, b, c]
对已存在的列,进行数据分类,函数为cut,默认使用区间类型为标签
In [5]:
pd.cut(np.random.randint(0,60,5), [0,10,30,60])
Out[5]:
[(10, 30], (0, 10], (10, 30], (30, 60], (30, 60]]
Categories (3, interval[int64]): [(0, 10] < (10, 30] < (30, 60]]
可指定字符为标签
pd.cut(np.random.randint(0,60,5), [0,10,30,60],
right=False, labels=['0-10','10-30','30-60'])
Out[6]:
[10-30, 30-60, 30-60, 10-30, 30-60]
Categories (3, object): [0-10 < 10-30 < 30-60]
2.获取分类数据的信息
一个分类变量包括三个部分,元素值(values)、分类类别(categories)、是否有序(order)
从上面可以看出,使用cut函数创建的分类变量默认为有序分类变量
下面介绍如何获取或修改这些属性
(a)describe方法¶
该方法描述了一个分类序列的情况,包括非缺失值个数、元素值类别数(不是分类类别数)、最多次出现的元素及其频数
describe()可以查看分类的统计信息。
In [7]:
s = pd.Series(pd.Categorical(["a", "b", "c", "a",np.nan], categories=['a','b','c','d']))
s.describe()
Out[7]:
count 4
unique 3
top a
freq 2
dtype: object
categories和ordered属性¶
查看分类类别和是否排序
In [8]:
s.cat.categories
Out[8]:
Index(['a', 'b', 'c', 'd'], dtype='object')
In [9]:
s.cat.ordered
Out[9]:
False
3.类别的修改
- 利用set_categories修改
修改分类,但本身值不会变化,只是把原数据放在新的分桶里。
In [10]:
s = pd.Series(pd.Categorical(["a", "b", "c", "a",np.nan], categories=['a','b','c','d']))
s.cat.set_categories(['new_a','c'])
Out[10]:
0 NaN
1 NaN
2 c
3 NaN
4 NaN
dtype: category
Categories (2, object): [new_a, c]
- 利用rename_categories修改
需要注意的是该方法会把值和分类同时修改(这里其实不是新建了分桶,只是把原有桶改了名,相当于新贴了个label,其实原数据也没有变)
In [11]:
s = pd.Series(pd.Categorical(["a", "b", "c", "a",np.nan], categories=['a','b','c','d']))
s.cat.rename_categories(['new_%s'%i for i in s.cat.categories])
Out[11]:
0 new_a
1 new_b
2 new_c
3 new_a
4 NaN
dtype: category
Categories (4, object): [new_a, new_b, new_c, new_d]
- 利用字典修改值,其实也是重命名
In [12]:
s.cat.rename_categories({'a':'new_a','b':'new_b'})
Out[12]:
0 new_a
1 new_b
2 c
3 new_a
4 NaN
dtype: category
Categories (4, object): [new_a, new_b, c, d]
- add添加新分组
In [13]:
s = pd.Series(pd.Categorical(["a", "b", "c", "a",np.nan], categories=['a','b','c','d']))
s.cat.add_categories(['e'])
Out[13]:
0 a
1 b
2 c
3 a
4 NaN
dtype: category
Categories (5, object): [a, b, c, d, e]
- 利用remove_categories移除
In [14]:
s = pd.Series(pd.Categorical(["a", "b", "c", "a",np.nan], categories=['a','b','c','d']))
s.cat.remove_categories(['d'])
Out[14]:
0 a
1 b
2 c
3 a
4 NaN
dtype: category
Categories (3, object): [a, b, c]
- 删除元素值未出现的分类类型
In [15]:
s = pd.Series(pd.Categorical(["a", "b", "c", "a",np.nan], categories=['a','b','c','d']))
s.cat.remove_unused_categories()
Out[15]:
0 a
1 b
2 c
3 a
4 NaN
dtype: category
Categories (3, object): [a, b, c]
4.分类数据的排序
分类数据类型被分为有序和无序,这非常好理解,例如分数区间的高低是有序变量,考试科目的类别一般看做无序变量。
- 一般来说会将一个序列转为有序变量,可以利用as_ordered方法
In [16]:
s = pd.Series(["a", "d", "c", "a"]).astype('category').cat.as_ordered()
s
Out[16]:
0 a
1 d
2 c
3 a
dtype: category
Categories (3, object): [a < c < d]
退化为无序变量,只需要使用as_unordered
In [17]:
s.cat.as_unordered()
同样也是值排序和索引排序,设置类别顺序,然后就可以值排序
s.cat.set_categories(['perfect','good','fair','bad',
'awful'][::-1],ordered=True).head()
Out[21]:
0 good
1 fair
2 bad
3 perfect
4 perfect
dtype: category
Categories (5, object): [awful < bad < fair < good < perfect]
按值排序
s.sort_values(ascending=False).head()
Out[22]:
29 perfect
17 perfect
31 perfect
3 perfect
4 perfect
dtype: category
Categories (5, object): [awful, bad, fair, good, perfect]
索引为类别时,可以按索引排序
df_sort = pd.DataFrame({'cat':s.values,
'value':np.random.randn(50)}).set_index('cat')
df_sort.head()
value
cat
good -1.746975
fair 0.836732
bad 0.094912
perfect -0.724338
perfect -1.456362
按索引排序(默认降序)
df_sort.sort_index().head()
Out[24]:
value
cat
awful 0.245782
awful 0.063991
awful 1.541862
awful -0.062976
awful 0.472542