分类
分类的目的是提高性能和内存的使用率
用整数表示的方法称为分类或者字典编码表示法,不同值的数组称为分类、字典或者数据集。
创建分类
- take方法存储原始字符串
Series
- 直接创建分类:
pd.Categorical(data)
- 转变成类:
df.astype('category')
- 分类对象属性
codes
categories
分类计算
- 面元函数
qcut
函数返回类Categories
对象:pd.qcut(draws, 4)
- 通过labels标签实现汇总
- groupby提取汇总信息
1 | import numpy as np |
1 | results = (pd.Series(draws) |
分类方法
memory_usage()
:查看内存cat()
:提供入口pd.cat.categories
pd.cat.codes
value_counts()
:查看具体分类- 创建虚拟变量,用0/1组成的矩阵
1 | values = pd.Series(['apple', 'orange', 'apple', 'apple'] * 2) |
array(['apple', 'orange'], dtype=object)
1 | pd.value_counts(values) # 计算每个值出现的频率 |
apple 6
orange 2
dtype: int64
数据系统使用包含不同值的维表Dimension Table ,将主要的参数存储为引用维表整数键
- take()方法:分类
去重显示
1 | values = pd.Series([0, 1, 0, 0] * 2) |
1 | print(values) |
0 0
1 1
2 0
3 0
4 0
5 1
6 0
7 0
dtype: int64
0 apple
1 orange
dtype: object
1 | dim.take(values) # take方法 |
0 apple
1 orange
0 apple
0 apple
0 apple
1 orange
0 apple
0 apple
dtype: object
pandas分类类型
1 | fruits = ['apple', 'orange', 'apple', 'apple'] * 2 |
1 | df = pd.DataFrame({'fruit': fruits, |
basket_id | fruit | count | weight | |
---|---|---|---|---|
0 | 0 | apple | 12 | 1.550912 |
1 | 1 | orange | 6 | 3.457292 |
2 | 2 | apple | 3 | 3.986303 |
3 | 3 | apple | 7 | 0.955448 |
4 | 4 | apple | 9 | 1.912784 |
5 | 5 | orange | 6 | 1.405372 |
6 | 6 | apple | 11 | 2.882363 |
7 | 7 | apple | 12 | 2.137783 |
转成分类
通过astype(‘category’)将某个属性转成分类类型
1 | # 转换成分类 |
0 apple
1 orange
2 apple
3 apple
4 apple
5 orange
6 apple
7 apple
Name: fruit, dtype: category
Categories (2, object): [apple, orange]
1 | print(type(fruit_cat)) # S型数据 |
1 | c = fruit_cat.valuest |
pandas.core.arrays.categorical.Categorical
两个属性值codes 和 categories
1 | # 分类对象有categories和codes属性 |
Index(['apple', 'orange'], dtype='object')
[0 1 0 0 0 1 0 0]
1 | df |
basket_id | fruit | count | weight | |
---|---|---|---|---|
0 | 0 | apple | 12 | 1.550912 |
1 | 1 | orange | 6 | 3.457292 |
2 | 2 | apple | 3 | 3.986303 |
3 | 3 | apple | 7 | 0.955448 |
4 | 4 | apple | 9 | 1.912784 |
5 | 5 | orange | 6 | 1.405372 |
6 | 6 | apple | 11 | 2.882363 |
7 | 7 | apple | 12 | 2.137783 |
1 | # 将列转换成分类 |
0 apple
1 orange
2 apple
3 apple
4 apple
5 orange
6 apple
7 apple
Name: fruit, dtype: category
Categories (2, object): [apple, orange]
1 | # 通过Python其他序列创建分类 |
[foo, bar, baz, foo, bar]
Categories (3, object): [bar, baz, foo]
1 | # 通过from_codes构建分类 |
[foo, bar, baz, foo, foo, bar]
Categories (3, object): [foo, bar, baz]
1 | # 无序的分类实例通过as_ordered进行排序 |
[foo, bar, baz, foo, foo, bar]
Categories (3, object): [foo < bar < baz]
1 | # 创建分类的实例直接指定顺序: ordered=True |
[foo, bar, baz, foo, foo, bar]
Categories (3, object): [foo < bar < baz]
分类计算
重点关注pandas
中的Categorical
类。通过使用pandas.qcut
面元函数,返回pandas.Categorical
- 创建面元
- 通过面元提取数据
1 | np.random.seed(12345) |
array([-0.20470766, 0.47894334, -0.51943872, -0.5557303 , 1.96578057])
1 | bins = pd.qcut(draws, 4) |
[(-0.684, -0.0101], (-0.0101, 0.63], (-0.684, -0.0101], (-0.684, -0.0101], (0.63, 3.928], ..., (-0.0101, 0.63], (-0.684, -0.0101], (-2.9499999999999997, -0.684], (-0.0101, 0.63], (0.63, 3.928]]
Length: 1000
Categories (4, interval[float64]): [(-2.9499999999999997, -0.684] < (-0.684, -0.0101] < (-0.0101, 0.63] < (0.63, 3.928]]
使用lables参数来qcut
1 | bins = pd.qcut(draws, 4, labels=['Q1', 'Q2', 'Q3', 'Q4']) |
[Q2, Q3, Q2, Q2, Q4, ..., Q3, Q2, Q1, Q3, Q4]
Length: 1000
Categories (4, object): [Q1 < Q2 < Q3 < Q4]
1 | bins.codes[:10] |
array([1, 2, 1, 1, 3, 3, 2, 2, 3, 3], dtype=int8)
1 | # groupby 提取汇总信息 |
quratile | count | min | max | |
---|---|---|---|---|
0 | Q1 | 250 | -2.949343 | -0.685484 |
1 | Q2 | 250 | -0.683066 | -0.010115 |
2 | Q3 | 250 | -0.010032 | 0.628894 |
3 | Q4 | 250 | 0.634238 | 3.927528 |
1 | bins = pd.Series(bins, name="quratile") |
count | min | max | |
---|---|---|---|
quratile | |||
Q1 | 250 | -2.949343 | -0.685484 |
Q2 | 250 | -0.683066 | -0.010115 |
Q3 | 250 | -0.010032 | 0.628894 |
Q4 | 250 | 0.634238 | 3.927528 |
1 | results["quratile"] |
0 Q1
1 Q2
2 Q3
3 Q4
Name: quratile, dtype: category
Categories (4, object): [Q1 < Q2 < Q3 < Q4]
分类提高性能
- 使用DF的列分类占用内存少
- memory_usage():查看内存
1 | N = 10000000 |
1 | categories = labels.astype("category") |
10000272
1 | labels.memory_usage() # 非分类占用内存多 |
80000080
1 | %time _ = labels.astype('category') |
Wall time: 444 ms
分类方法
- 先使用分类入口:
cat
方法;再使用codes,categories
方法- cat.codes
- cat.categories
- set_categories:解决超出给定的数据集个数
- value_counts():查看分类的个数
- remove_unused_categories():删除没有看到的数据
- 常用方法汇总
方法 | 作用 |
---|---|
add_categories | 已存在分类的后面直接添加 |
as_ordered | 使分类有序 |
as_unordered | 使分类无序 |
remove_categories | 移除分类,设置移除值为null |
remove_unused_categories | 移除任意不出现在数据中的分类值 |
set_categories | 用指定的新分类的名字来替换分类,可以添加或者删除分类 |
1 | s = pd.Series(['a', 'b', 'c', 'd'] * 2) |
0 a
1 b
2 c
3 d
4 a
5 b
6 c
7 d
dtype: category
Categories (4, object): [a, b, c, d]
1 | # cat属性提供分类方法的入口 |
0 0
1 1
2 2
3 3
4 0
5 1
6 2
7 3
dtype: int8
1 | cat_s.cat.categories |
Index(['a', 'b', 'c', 'd'], dtype='object')
1 | # 实际分类超出给定数据集中的个数,通过set_catgories实现 |
0 a
1 b
2 c
3 d
4 a
5 b
6 c
7 d
dtype: category
Categories (5, object): [a, b, c, d, e]
1 | # 统计每个类的分类值 |
d 2
c 2
b 2
a 2
dtype: int64
1 | cat_s2.value_counts() |
d 2
c 2
b 2
a 2
e 0
dtype: int64
1 | # remove_unused_categories() |
0 a
1 b
4 a
5 b
dtype: category
Categories (4, object): [a, b, c, d]
1 | cat_s.isin(['a', 'b']) |
0 True
1 True
2 False
3 False
4 True
5 True
6 False
7 False
dtype: bool
1 | # 查看分类,变成2个 |
0 a
1 b
4 a
5 b
dtype: category
Categories (2, object): [a, b]
创建虚拟变量
虚拟变量创建的过程实际上是将各个分类的标签看成是列属性,存在的数据则是1,不存在则是0,创建0/1矩阵
- 分类数据转成虚拟变量:one-hot编码
- 创建值为0或者1的DF数据
- pd.get_dummies()
1 | cat_s = pd.Series(['a', 'b', 'c', 'd'] * 2, dtype='category') |
a | b | c | d | |
---|---|---|---|---|
0 | 1 | 0 | 0 | 0 |
1 | 0 | 1 | 0 | 0 |
2 | 0 | 0 | 1 | 0 |
3 | 0 | 0 | 0 | 1 |
4 | 1 | 0 | 0 | 0 |
5 | 0 | 1 | 0 | 0 |
6 | 0 | 0 | 1 | 0 |
7 | 0 | 0 | 0 | 1 |
1 | cat_s |
0 a
1 b
2 c
3 d
4 a
5 b
6 c
7 d
dtype: category
Categories (4, object): [a, b, c, d]