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