美文网首页
2020-08-06--Pandas-05--分类数据处理

2020-08-06--Pandas-05--分类数据处理

作者: program_white | 来源:发表于2020-08-06 12:18 被阅读0次

来看看 Pandas 中分类(category)数据如何处理吧。

创建分类对象

1.使用dtype="category"创建

在创建分类数据之前,先来了解下什么是分类(Category)数据呢?分类数据直白来说就是取值为有限的,或者说是固定数量的可能值。例如:性别、血型。

这里以血型为例,假定每个用户有以下的血型,我们如何创建一个关于血型的分类对象呢?

一种有效的方法就是明确指定 dtype="category"

import pandas as pd
import numpy as np

index = pd.Index(data=['Tom','Bob','Mary','James','Andy','Alice'])

user_info = pd.Series(data=['A','AB',np.nan,'AB','O','B'],index=index,name='blood_type',dtype='category')

print(user_info)
# Tom        A
# Bob       AB
# Mary     NaN
# James     AB
# Andy       O
# Alice      B
# Name: blood_type, dtype: category
# Categories (4, object): ['A', 'AB', 'B', 'O']

2.使用pd.Categorical 创建

# categories:指定存储的分类信息
c = pd.Categorical(["A", "AB", np.nan, "AB", "O", "B"], categories=["A", "B", "AB"])
print(c)
# ['A', 'AB', NaN, 'AB', NaN, 'B']
# Categories (3, object): ['A', 'B', 'AB']

3.astype

除了上面这些方法外,经常遇到的情况是已经创建了一个 Series,如何将它转为分类数据呢?来看看 astype 用法吧。

user_info = pd.Series(data=["A", "AB", np.nan, "AB", "O", "B"], index=index, name="blood_type")
user_info = user_info.astype("category")
print(user_info)
# Tom        A
# Bob       AB
# Mary     NaN
# James     AB
# Andy       O
# Alice      B
# Name: blood_type, dtype: category
# Categories (4, object): ['A', 'AB', 'B', 'O']

此外,一些其他的方法返回的结果也是分类数据。如 cut 、 qcut。具体可以见 Pandas基本功能详解中的离散化部分。

常用操作

统计

可以对分类数据使用 .describe() 方法。

c = user_info.describe()
print(c)
# count      5
# unique     4
# top       AB
# freq       2
# Name: blood_type, dtype: object

解释下每个指标的含义,count 表示非空的数据有5条,unique 表示去重后的非空数据有4条,top 表示出现次数最多的值为 AB,freq 表示出现次数最多的值的次数为2次。

分类数据的取值

我们可以使用 .cat.categories 来获取分类数据所有可能的取值。

c = user_info.cat.categories
print(c)
# Index(['A', 'AB', 'B', 'O'], dtype='object')

修改分类名称

user_info = user_info.cat.rename_categories(["A+", "AB+", "B+", "O+"])
print(user_info)
# Tom       A+
# Bob      AB+
# Mary     NaN
# James    AB+
# Andy      O+
# Alice     B+
# Name: blood_type, dtype: category
# Categories (4, object): ['A+', 'AB+', 'B+', 'O+']

修改分类名称后,也会将数据中的对应进行修改。

类似的,除了重命名,也会遇到添加类别,删除分类的操作,这些都可以通过 .cat.add_categories ,.cat.remove_categories 来实现。

user_info = user_info.cat.add_categories(["C"])
print(user_info)
# Tom       A+
# Bob      AB+
# Mary     NaN
# James    AB+
# Andy      O+
# Alice     B+
# Name: blood_type, dtype: category
# Categories (5, object): ['A+', 'AB+', 'B+', 'O+', 'C']

查看数据分布统计

分类数据也是支持使用 value_counts 方法来查看数据分布的。

c = user_info.value_counts()
print(c)
# AB+    2
# O+     1
# B+     1
# A+     1
# C      0
# Name: blood_type, dtype: int64

.str

分类数据也是支持使用 .str 属性来访问的。例如想要查看下是否包含字母 "A",可以使用 .srt.contains 方法。

c = user_info.str.contains('A')
print(c)
# Tom       True
# Bob       True
# Mary       NaN
# James     True
# Andy     False
# Alice    False
# Name: blood_type, dtype: object

返回一个bool值的Series序列,利用花式索引可以获取到符合条件的数据。

更多关于 .str 的详细介绍可以见 Pandas文本数据处理。

合并数据

pd.concat([Series,Series])

blood_type1 = pd.Categorical(["A", "AB"])
blood_type2 = pd.Categorical(["B", "O"])

c = pd.concat([pd.Series(blood_type1), pd.Series(blood_type2)])

print(c)
# 0     A
# 1    AB
# 0     B
# 1     O
# dtype: object

可以发现,分类数据经过 pd.concat 合并后类型转为了 object 类型。如果想要保持分类类型的话,可以借助 union_categoricals 来完成。

from pandas.api.types import union_categoricals

c = union_categoricals([blood_type1, blood_type2])
print(c)
# 0     A
# 1    AB
# 0     B
# 1     O
# dtype: object
# ['A', 'AB', 'B', 'O']
# Categories (4, object): ['A', 'AB', 'B', 'O']

分类数据与Series序列的内存对比

blood_type = pd.Series(["AB","O"]*1000)
blood_type.nbytes
16000
blood_type.astype("category").nbytes
2016

对比下,是不是发现分类数据非常节省内存。但是当类别的数量接近数据的长度,那么 Categorical 将使用与等效的 object 表示几乎相同或更多的内存。

blood_type = pd.Series(['AB%04d' % i for i in range(2000)])
blood_type.nbytes
16000
blood_type.astype("category").nbytes
20000

相关文章

网友评论

      本文标题:2020-08-06--Pandas-05--分类数据处理

      本文链接:https://www.haomeiwen.com/subject/nhrzrktx.html