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

来看看 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
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,924评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,781评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,813评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,264评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,273评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,383评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,800评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,482评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,673评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,497评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,545评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,240评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,802评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,866评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,101评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,673评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,245评论 2 341