python pandas数据分箱
0 背景
数据分箱(也称为分段或桶分析)是一种数据预处理技术,用于将连续变量转换为多个离散的分箱或桶。在 Pandas 中,数据分箱主要通过两个函数实现:pd.cut()
和 pd.qcut()
。
1. pd.cut()
这个函数用于根据指定的边界对数据进行分箱。我们可以自定义每个箱子的范围。它适用于以下场景:
-
当你有特定的分箱边界或希望每个箱子具有相同的宽度时。 -
用于将数据分成类别,如年龄组、收入区间、学生的分数区间等。 -
常用于业务分析,比如将客户根据消费金额分为不同级别。
2. pd.qcut()
这个函数基于数据的分位数进行分箱,确保每个箱子包含大致相同数量的数据点。它的应用场景包括:
-
当我们希望每个箱子包含相同数量的观测值时。 -
适用于需要根据数据分布进行分箱的场景,比如将考试成绩分为四分位,每个分位包含25%的学生。 -
对于偏态分布的数据, pd.qcut()
可以确保每个箱子具有更均匀的数据点分布。
1 使用
1 导入和初始化数据
import pandas as pd
import numpy as np
data = {'A': ['aa', 'ab', 'bc', 'bc', 'ab', 'bc'],
'B': [2, 2, 3, 5, 8, 5],
'C': [0.21, -1.08, -0.02, 0.68, 0.78, 0.23],
'D': [-0.86, -0.16, 0.74, 1.21, 1.18, 0.71],
'E': [2, 5, 7, 2, 4, 8]}
df = pd.DataFrame(data)
df
A B C D E
0 aa 2 0.21 -0.86 2
1 ab 2 -1.08 -0.16 5
2 bc 3 -0.02 0.74 7
3 bc 5 0.68 1.21 2
4 ab 8 0.78 1.18 4
5 bc 5 0.23 0.71 8
2 定界分箱pd.cut()
pd.cut()
可以指定区间对数字进行划分。
cut_ = pd.cut(df.E, bins=[0, 3, 6, 10], )
cut_
# 0 (0, 3]
# 1 (3, 6]
# 2 (6, 10]
# 3 (0, 3]
# 4 (3, 6]
# 5 (6, 10]
# Name: E, dtype: category
# Categories (3, interval[int64, right]): [(0, 3] < (3, 6] < (6, 10]]
应用到分组中去
# 应用到分组当中
df.B.groupby(cut_).mean()
# E
# (0, 3] 3.5
# (3, 6] 5.0
# (6, 10] 4.0
# Name: B, dtype: float64
箱子的标签分布
# labels=False 不使用区间作为标签,使用数字作为每个分箱的标签,如0...n
pd.cut(df.E, bins=[0, 3, 6, 10], labels=False)
# 0 0
# 1 1
# 2 2
# 3 0
# 4 1
# 5 2
# Name: E, dtype: int64
# 指定标签
pd.cut(df.E, bins=[0, 3, 6, 10], labels=['不及格', '及格', '优秀'])
# 0 不及格
# 1 及格
# 2 优秀
# 3 不及格
# 4 及格
# 5 优秀
# Name: E, dtype: category
# Categories (3, object): ['不及格' < '及格' < '优秀']
# include_lowest=True 表示第一个区间会包括其左端点。比如,如果区间是 [0, 60],那么数值 0 会被包含在这个区间内。当 include_lowest=False(默认值)时,第一个区间不包括其左端点。数值 0 则不会被包含在 [0, 60] 这个区间内。
pd.cut(df.E, bins=[0, 3, 6, 10], include_lowest=True)
# 0 (-0.001, 3.0]
# 1 (3.0, 6.0]
# 2 (6.0, 10.0]
# 3 (-0.001, 3.0]
# 4 (3.0, 6.0]
# 5 (6.0, 10.0]
# Name: E, dtype: category
# Categories (3, interval[float64, right]): [(-0.001, 3.0] < (3.0, 6.0] < (6.0, 10.0]]
# right=False 表示分箱区间是左开右闭,比如,如果区间是 [0, 60],那么数值 0
pd.cut(df.E, bins=[0, 3, 6, 10], right=False)
# 0 [0, 3)
# 1 [3, 6)
# 2 [6, 10)
# 3 [0, 3)
# 4 [3, 6)
# 5 [6, 10)
# Name: E, dtype: category
# Categories (3, interval[int64, left]): [[0, 3) < [3, 6) < [6, 10)]
3 等宽分箱pd.qcut()
pd.qcut() 函数在 Pandas 中用于数据的等频(而非等宽)分箱。这意味着它按照数据的分位数将数据集分成具有大致相等数量数据点的几个箱子,而不是按照相等的间隔宽度。例如,如果你对一组数据使用 pd.qcut() 并指定 4 个箱子,那么每个箱子将包含大约 25% 的数据点,分别对应整体数据的第一个四分位数、第二个四分位数(中位数)、第三个四分位数和最大值。因此,pd.qcut() 是基于数据的分布而非固定的间隔宽度来划分数据的。
pd.qcut(df.E, q=3)
# 0 (1.999, 3.333]
# 1 (3.333, 5.667]
# 2 (5.667, 8.0]
# 3 (1.999, 3.333]
# 4 (3.333, 5.667]
# 5 (5.667, 8.0]
# Name: E, dtype: category
# Categories (3, interval[float64, right]): [(1.999, 3.333] < (3.333, 5.667] < (5.667, 8.0]]
应用到分组当中
# 应用到分组中
df.B.groupby(pd.qcut(df.E, q=4), observed=True).count()
# E
# (1.999, 2.5] 2
# (2.5, 4.5] 1
# (4.5, 6.5] 1
# (6.5, 8.0] 2
# Name: B, dtype: int64
其他用法如下:
# 对列表进行分箱
pd.qcut(range(10), q=3, labels=False)
pd.qcut(range(10), q=3)
pd.qcut(range(5), 3, labels=["好", "中", "差"])
# ['好', '好', '中', '差', '差']
# 返回箱子标签 array([...]))
pd.qcut(df.E, q=2, retbins=True)
# (0 (1.999, 4.5]
# 1 (4.5, 8.0]
# 2 (4.5, 8.0]
# 3 (1.999, 4.5]
# 4 (1.999, 4.5]
# 5 (4.5, 8.0]
# Name: E, dtype: category
# Categories (2, interval[float64, right]): [(1.999, 4.5] < (4.5, 8.0]],
# array([2. , 4.5, 8. ]))
# precision: 整数,表示在返回的区间中小数点后保留的位数。
pd.qcut(df.E, q=3, precision=3)
# 0 (1.999, 3.333]
# 1 (3.333, 5.667]
# 2 (5.667, 8.0]
# 3 (1.999, 3.333]
# 4 (3.333, 5.667]
# 5 (5.667, 8.0]
# Name: E, dtype: category
# Categories (3, interval[float64, right]): [(1.999, 3.333] < (3.333, 5.667] < (5.667, 8.0]]
# 对排名而不是数值进行分箱,分3个等级
pd.qcut(df.E.rank(method='first'), 3)
# 0 (0.999, 2.667]
# 1 (2.667, 4.333]
# 2 (4.333, 6.0]
# 3 (0.999, 2.667]
# 4 (2.667, 4.333]
# 5 (4.333, 6.0]
# Name: E, dtype: category
# Categories (3, interval[float64, right]): [(0.999, 2.667] < (2.667, 4.333] < (4.333, 6.0]]
2 其他
欢迎关注我的微信公众号
原文始发于微信公众号(其之):python pandas数据分箱
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/204764.html