(5条消息) pandas中category类型的数据处理

pandas中category类型的数据

  • 用途和特点
    • 常见的问题处理
    • Categorical 数据

用途和特点

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

常见的问题处理

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

import numpy as npimport pandas as pdlst=[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 npimport pandas as pdlst=[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]: dfOut[5]:    A  B0  a  a1  b  b2  c  c3  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    group0     65  60 - 691     49  40 - 492     56  50 - 593     43  40 - 494     43  40 - 495     91  90 - 996     32  30 - 397     87  80 - 898     36  30 - 399      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]: sOut[12]: 0    NaN1      b2      c3    NaNdtype: categoryCategories (3, object): [b, c, d]In [13]: df = pd.DataFrame({"A": ["a", "b", "c", "a"]})In [14]: df["B"] = raw_catIn [15]: dfOut[15]:    A    B0  a  NaN1  b    b2  c    c3  a  NaN

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

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

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

from pandas.api.types import CategoricalDtypes = 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.categoriesOut[58]: Index(['a', 'b', 'c'], dtype='object')In [59]: s.cat.orderedOut[59]: False

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

In [60]: s = pd.Series(pd.Categorical(["a", "b", "c", "a"],   ....:               categories=["c", "b", "a"]))   ....: In [61]: s.cat.categoriesOut[61]: Index(['c', 'b', 'a'], dtype='object')In [62]: s.cat.orderedOut[62]: False

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

4、重命名

In [67]: s = pd.Series(["a", "b", "c", "a"], dtype="category")In [68]: sOut[68]: 0    a1    b2    c3    adtype: categoryCategories (3, object): [a, b, c]In [69]: s.cat.categories = ["Group %s" % g for g in s.cat.categories]In [70]: sOut[70]: 0    Group a1    Group b2    Group c3    Group adtype: categoryCategories (3, object): [Group a, Group b, Group c]In [71]: s = s.cat.rename_categories([1, 2, 3])In [72]: sOut[72]: 0    11    22    33    1dtype: categoryCategories (3, int64): [1, 2, 3]# You can also pass a dict-like object to map the renamingIn [73]: s = s.cat.rename_categories({1: 'x', 2: 'y', 3: 'z'})In [74]: sOut[74]: 0    x1    y2    z3    xdtype: categoryCategories (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.categoriesOut[78]: Index(['x', 'y', 'z', 4], dtype='object')In [79]: sOut[79]: 0    x1    y2    z3    xdtype: categoryCategories (4, object): [x, y, z, 4]

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

In [80]: s = s.cat.remove_categories([4])In [81]: sOut[81]: 0    x1    y2    z3    xdtype: categoryCategories (3, object): [x, y, z]

7、删除未使用的类别

In [82]: s = pd.Series(pd.Categorical(["a", "b", "a"],   ....:               categories=["a", "b", "c", "d"]))   ....: In [83]: sOut[83]: 0    a1    b2    adtype: categoryCategories (4, object): [a, b, c, d]In [84]: s.cat.remove_unused_categories()Out[84]: 0    a1    b2    adtype: categoryCategories (2, object): [a, b]

8、设置类别

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

In [85]: s = pd.Series(["one", "two", "four", "-"], dtype="category")In [86]: sOut[86]: 0     one1     two2    four3       -dtype: categoryCategories (4, object): [-, four, one, two]In [87]: s = s.cat.set_categories(["one", "two", "three", "four"])In [88]: sOut[88]: 0     one1     two2    four3     NaNdtype: categoryCategories (4, object): [one, two, three, four]```9、排序和顺序```pythonIn [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]: sOut[93]: 0    a3    a1    b2    cdtype: categoryCategories (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    a3    a1    b2    cdtype: categoryCategories (3, object): [a < b < c]In [96]: s.cat.as_unordered()Out[96]: 0    a3    a1    b2    cdtype: categoryCategories (3, object): [a, b, c]```这些基本上够用的了,想了解更深的可以查看[官网资料](https://pandas.pydata.org/pandas-docs/stable/user_guide/categorical.html)。
(0)

相关推荐