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)。