pandas中category类型的数据处理

用途和特点

category是pandas中定义的一个数据类型,相当于R中的因子。可以对特点的类型数据进行按照自己的意愿进行排序,特别是我们在处理数据是需要对字符串进行排序时,有时候默认的顺序真的很无奈。这个时候就是这个类型该入场的时候了。下面我们看下这个类型的具体使用情况。

常见的问题处理

在日常数据处理中使用pd.cut或pd.qcut时,默认分组标签就是category类型,不知道你处理时是否头疼过。不过这个确实给我们想向里面加数据时带来了麻烦,例如以下情况:

import numpy as np
import pandas as pd
lst=[np.nan,np.nan]
lst.extend(range(1,100))
data=pd.DataFrame({'A':lst ,'B':np.random.randn(101)})
#想把缺失值分成一个组,先不处理缺失值
data['group']=pd.cut(data['A'],10)
#分组后填充缺失值

data['group'].fillna('空缺')

这样就会报如下错误:
在这里插入图片描述
当然了这里你可以把分组标签转成字符串处理,但是会出现排序不理想的情况。这里可以这样完美解决。

import numpy as np
import pandas as pd
lst=[np.nan,np.nan]
lst.extend(range(1,100))
data=pd.DataFrame({'A':lst ,'B':np.random.randn(101)})
#想把缺失值分成一个组,先不处理缺失值
data['group']=pd.cut(data['A'],10)
#分组后填充缺失值
data['group']=data['group'].cat.add_categories(['空缺'])
data['group'].fillna('空缺')

这个是为什么?不要急下面就说原因。

Categorical 数据

这里可以参考文档:pandas文档
上面已经说了,categorical类型是pandas中定义的一个变量。
1、Series的创建
可以通过几种方式创建类别中的类别Series或列DataFrame:
通过指定dtype="category"在构造时Series:

s = pd.Series(["a", "b", "c", "a"],dtype="category")
s

输出:
在这里插入图片描述
通过将现有的Series或列转换为categorydtype:

In [3]: df = pd.DataFrame({"A": ["a", "b", "c", "a"]})

In [4]: df["B"] = df["A"].astype('category')

In [5]: df
Out[5]: 
   A  B
0  a  a
1  b  b
2  c  c
3  a  a

通过使用特殊功能(例如)cut(),可以将数据分组为离散的bin。请参阅文档中有关的示例

In [6]: df = pd.DataFrame({'value': np.random.randint(0, 100, 20)})

In [7]: labels = ["{0} - {1}".format(i, i + 9) for i in range(0, 100, 10)]

In [8]: df['group'] = pd.cut(df.value, range(0, 105, 10), right=False, labels=labels)

In [9]: df.head(10)
Out[9]: 
   value    group
0     65  60 - 69
1     49  40 - 49
2     56  50 - 59
3     43  40 - 49
4     43  40 - 49
5     91  90 - 99
6     32  30 - 39
7     87  80 - 89
8     36  30 - 39
9      8    0 - 9

通过将pandas.Categorical对象传递给Series或将其分配给DataFrame。

In [10]: raw_cat = pd.Categorical(["a", "b", "c", "a"], categories=["b", "c", "d"],
   ....:                          ordered=False)
   ....: 

In [11]: s = pd.Series(raw_cat)

In [12]: s
Out[12]: 
0    NaN
1      b
2      c
3    NaN
dtype: category
Categories (3, object): [b, c, d]

In [13]: df = pd.DataFrame({"A": ["a", "b", "c", "a"]})

In [14]: df["B"] = raw_cat

In [15]: df
Out[15]: 
   A    B
0  a  NaN
1  b    b
2  c    c
3  a  NaN

2、DataFrame 创建
可以在创建时dataframe时,定义

In [17]: df = pd.DataFrame({'A': list('abca'), 'B': list('bccd')}, dtype="category")

In [18]: df.dtypes
Out[18]: 
A    category
B    category
dtype: object

3、控制category
通过上面的例子可能已经对这个类型有所了解了。下面我们看下它的强大之处。

from pandas.api.types import CategoricalDtype
s = pd.Series(["a", "b", "c", "a","d","e"])
cat_type = CategoricalDtype(categories=["b", "c", "a"],ordered=True)#categories必须是一个列表
s_cat = s.astype(cat_type)
s_cat

输出:
在这里插入图片描述
这里,我们定义一个Categorical类型数据,没有定义在列表的值被置成了NaN值。我们再看下结果中[b < c < a],这个排序和python默认序列已经不一样了。

Categorical类型数据我们定义后,是一个固定的列表了,我们不能直接添加没有定义的类别。这里就需要对类型数据进行操作了。

3、类型数据的基本操作
分类数据具有类别和有序属性,它们列出了它们的可能值以及排序是否重要。这些属性在s.cat.categories和中公开s.cat.ordered。如果您不手动指定类别和顺序,则可以从传递的参数中推断出它们。

In [57]: s = pd.Series(["a", "b", "c", "a"], dtype="category")

In [58]: s.cat.categories
Out[58]: Index(['a', 'b', 'c'], dtype='object')

In [59]: s.cat.ordered
Out[59]: False

也可以按特定顺序传递类别:

In [60]: s = pd.Series(pd.Categorical(["a", "b", "c", "a"],
   ....:               categories=["c", "b", "a"]))
   ....: 

In [61]: s.cat.categories
Out[61]: Index(['c', 'b', 'a'], dtype='object')

In [62]: s.cat.ordered
Out[62]: False

这里注意:新的分类数据不会自动排序。您必须明确传递ordered=True以指示已定义的Categorical

4、重命名

In [67]: s = pd.Series(["a", "b", "c", "a"], dtype="category")

In [68]: s
Out[68]: 
0    a
1    b
2    c
3    a
dtype: category
Categories (3, object): [a, b, c]

In [69]: s.cat.categories = ["Group %s" % g for g in s.cat.categories]

In [70]: s
Out[70]: 
0    Group a
1    Group b
2    Group c
3    Group a
dtype: category
Categories (3, object): [Group a, Group b, Group c]

In [71]: s = s.cat.rename_categories([1, 2, 3])

In [72]: s
Out[72]: 
0    1
1    2
2    3
3    1
dtype: category
Categories (3, int64): [1, 2, 3]

# You can also pass a dict-like object to map the renaming
In [73]: s = s.cat.rename_categories({1: 'x', 2: 'y', 3: 'z'})

In [74]: s
Out[74]: 
0    x
1    y
2    z
3    x
dtype: category
Categories (3, object): [x, y, z]

请注意,分配新类别是一个就地操作,而Series.cat默认情况下,大多数其他操作将返回一个新Series的dtype category。

这里类别必须是唯一和非NaN值,否知会报错

In [75]: try:
   ....:     s.cat.categories = [1, 1, 1]
   ....: except ValueError as e:
   ....:     print("ValueError:", str(e))
   ....: 
ValueError: Categorical categories must be unique
In [76]: try:
   ....:     s.cat.categories = [1, 2, np.nan]
   ....: except ValueError as e:
   ....:     print("ValueError:", str(e))
   ....: 
ValueError: Categorial categories cannot be null

5、追加新的类别
可以使用以下.cat.add_categories()方法完成附加类别 :

In [77]: s = s.cat.add_categories([4])

In [78]: s.cat.categories
Out[78]: Index(['x', 'y', 'z', 4], dtype='object')

In [79]: s
Out[79]: 
0    x
1    y
2    z
3    x
dtype: category
Categories (4, object): [x, y, z, 4]

6、删除类别
删除类别可以通过使用.cat.remove_categories()方法来完成 。删除的值将替换为np.nan。

In [80]: s = s.cat.remove_categories([4])

In [81]: s
Out[81]: 
0    x
1    y
2    z
3    x
dtype: category
Categories (3, object): [x, y, z]

7、删除未使用的类别

In [82]: s = pd.Series(pd.Categorical(["a", "b", "a"],
   ....:               categories=["a", "b", "c", "d"]))
   ....: 

In [83]: s
Out[83]: 
0    a
1    b
2    a
dtype: category
Categories (4, object): [a, b, c, d]

In [84]: s.cat.remove_unused_categories()
Out[84]: 
0    a
1    b
2    a
dtype: category
Categories (2, object): [a, b]

8、设置类别

一步一步的删除和添加新类别,相对比较麻烦,可以使用.cat.set_categories来设置。

In [85]: s = pd.Series(["one", "two", "four", "-"], dtype="category")

In [86]: s
Out[86]: 
0     one
1     two
2    four
3       -
dtype: category
Categories (4, object): [-, four, one, two]

In [87]: s = s.cat.set_categories(["one", "two", "three", "four"])

In [88]: s
Out[88]: 
0     one
1     two
2    four
3     NaN
dtype: category
Categories (4, object): [one, two, three, four]```


9、排序和顺序

```python
In [89]: s = pd.Series(pd.Categorical(["a", "b", "c", "a"], ordered=False))

In [90]: s.sort_values(inplace=True)

In [91]: s = pd.Series(["a", "b", "c", "a"]).astype(
   ....:     CategoricalDtype(ordered=True)
   ....: )
   ....: 

In [92]: s.sort_values(inplace=True)

In [93]: s
Out[93]: 
0    a
3    a
1    b
2    c
dtype: category
Categories (3, object): [a < b < c]

In [94]: s.min(), s.max()
Out[94]: ('a', 'c')

或者使用.cat.as_ordered()排序

In [95]: s.cat.as_ordered()
Out[95]: 
0    a
3    a
1    b
2    c
dtype: category
Categories (3, object): [a < b < c]

In [96]: s.cat.as_unordered()
Out[96]: 
0    a
3    a
1    b
2    c
dtype: category
Categories (3, object): [a, b, c]```

这些基本上够用的了,想了解更深的可以查看[官网资料](https://pandas.pydata.org/pandas-docs/stable/user_guide/categorical.html)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值