Pandas pd.qcut() 函数
pd.qcut() 是 Pandas 库中用于按分位数进行分箱的函数。它将数据划分为相等数量的样本,每个箱子包含大约相同数量的数据点。
与 pd.cut()(等宽分箱)不同,pd.qcut() 确保每个区间内的数据量相等,非常适合处理偏态分布的数据,或者需要按照数据的自然分位数来划分的情况。
单词释义: qcut 中 "q" 代表 "quantile"(分位数),意思是按分位数来"切割"数据。
基本语法与参数
pd.qcut() 是 Pandas 库的顶级函数,用于基于分位数进行离散化。
语法格式
pd.qcut(x, q, labels=None, retbins=False, precision=3, duplicates='raise')
参数说明
- 参数:
x- 类型: 数组-like 对象,如列表、Series、数组等。
- 描述: 要进行分箱的连续数值数据。
- 参数:
q- 类型: 整数或分位数数组。
- 描述: 分箱的数量或具体的分位数。如果是一个整数 n,表示将数据分成 n 个等量的组(每个组约有 n/1 的数据)。也可以是一个分位数数组(如 [0, 0.25, 0.5, 0.75, 1.0])。
- 参数:
labels- 类型: 数组或 None。
- 描述: 为每个区间指定自定义标签。如果不指定,则使用分位数表示(如 "(0, 25]")。
- 参数:
retbins- 类型: 布尔值。
- 描述> 如果为
True,返回结果中包含分箱的边界值。默认为False。
- 参数:
duplicates- 类型: 字符串('raise' 或 'drop')。
- 描述> 如果分箱边界有重复(导致区间数量少于指定的 q 值),
'raise'会抛出异常,'drop'会删除重复的边界。默认为'raise'。
函数说明
- 返回值: 返回一个 Categorical 类型的 Series,每个值对应其所属的分位数组。
- 效果: 将连续数值按分位数映射为离散的类别,每个类别包含约相同数量的样本。
实例
让我们通过一系列从简单到复杂的例子,彻底掌握 pd.qcut() 的用法。
示例 1:基础用法 - 按四分位数分箱( quartile)
实例
import pandas as pd
import numpy as np
# 1. 创建有偏斜的数值数据(大部分值较小)
np.random.seed(42)
data = np.random.exponential(scale=2, size=100) # 指数分布数据
# 为了可读性,取部分数据
scores = pd.Series(data[:20])
print("=== 原始数据 ===")
print(scores.sort_values().values)
# 2. 使用 pd.qcut() 将数据分成 4 个分位数组( quartile)
result = pd.qcut(scores, q=4)
print("\n=== pd.qcut(scores, q=4) 四分位分箱 ===")
print(result.value_counts().sort_index())
import numpy as np
# 1. 创建有偏斜的数值数据(大部分值较小)
np.random.seed(42)
data = np.random.exponential(scale=2, size=100) # 指数分布数据
# 为了可读性,取部分数据
scores = pd.Series(data[:20])
print("=== 原始数据 ===")
print(scores.sort_values().values)
# 2. 使用 pd.qcut() 将数据分成 4 个分位数组( quartile)
result = pd.qcut(scores, q=4)
print("\n=== pd.qcut(scores, q=4) 四分位分箱 ===")
print(result.value_counts().sort_index())
运行结果预期:
=== 原始数据 === [ 0.078 0.29 0.68 0.91 1.03 1.06 1.23 1.3 1.5 1.69 1.86 2.01 2.12 2.3 2.32 2.42 3.03 3.39 5.29 7.39] === pd.qcut(scores, q=4) 四分位分箱 === (0.0783, 1.547] 5 (1.547, 2.315] 5 (2.315, 3.151] 5 (3.151, 7.393] 5 dtype: int64
代码解析:
- 对于指数分布的数据,如果使用等宽分箱,大部分数据会集中在一个箱内。
pd.qcut()确保每个箱内有大约相同数量的样本(这里是 5 个,正好是 20/4)。- 分位点是根据数据的实际分布计算出来的,而不是均匀划分的。
示例 2:指定自定义分位数
可以通过 q 参数指定任意的分位数,如十分位数、百分位数等。
实例
import pandas as pd
import numpy as np
# 1. 创建数据
df = pd.DataFrame({
'name': ['Student_' + str(i) for i in range(1, 11)],
'score': [65, 78, 82, 55, 90, 72, 68, 85, 45, 95]
})
print("=== 学生成绩数据 ===")
print(df)
# 2. 按自定义分位数分箱 [0, 0.3, 0.7, 1.0] 表示 30% 70% 100%
result = pd.qcut(df['score'], q=[0, 0.3, 0.7, 1.0])
print("\n=== 按 30% 和 70% 分位数分箱 ===")
print(result)
# 3. 添加自定义标签
labels = ['及格', '良好', '优秀']
result_labeled = pd.qcut(df['score'], q=3, labels=labels)
print("\n=== 添加自定义标签 ===")
print(result_labeled)
import numpy as np
# 1. 创建数据
df = pd.DataFrame({
'name': ['Student_' + str(i) for i in range(1, 11)],
'score': [65, 78, 82, 55, 90, 72, 68, 85, 45, 95]
})
print("=== 学生成绩数据 ===")
print(df)
# 2. 按自定义分位数分箱 [0, 0.3, 0.7, 1.0] 表示 30% 70% 100%
result = pd.qcut(df['score'], q=[0, 0.3, 0.7, 1.0])
print("\n=== 按 30% 和 70% 分位数分箱 ===")
print(result)
# 3. 添加自定义标签
labels = ['及格', '良好', '优秀']
result_labeled = pd.qcut(df['score'], q=3, labels=labels)
print("\n=== 添加自定义标签 ===")
print(result_labeled)
运行结果预期:
=== 学生成绩数据 ===
name score
0 Student_1 65
1 Student_2 78
2 Student_3 82
3 Student_4 55
4 Student_5 90
5 Student_6 72
6 Student_7 68
7 Student_8 85
8 Student_9 45
9 Student_10 95
=== 按 30% 和 70% 分位数分箱 ===
0 (44.999, 65.8]
1 (65.8, 86.4]
2 (65.8, 86.4]
3 (44.999, 65.8]
4 (86.4, 95.0]
5 (65.8, 86. 86.4]
6 (0.0, 44.999]
7 (44.999, 65.8]
8 (0.0, 44.999]
9 (65.8, 86.4]
10 (65.8, 86.4]
代码解析:
q=[0, 0.3, 0.7, 1.0]定义了 0-30%(低分),30%-70%(中等),70%-100%(高分)三个区间。- 使用
labels参数可以给每个区间命名,代替默认的区间表示。
示例 3:cut vs qcut 对比
通过对比可以更清楚地理解 cut 和 qcut 的区别。
实例
import pandas as pd
import numpy as np
# 1. 创建有偏斜的数据(大部分值较小)
data = pd.Series([1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 20, 30, 40, 50])
print("=== 原始数据 ===")
print(data.values)
# 2. 等宽分箱 (pd.cut)
print("\n=== pd.cut 等宽分箱 ===")
cut_result = pd.cut(data, bins=4)
print(cut_result.value_counts().sort_index())
# 3. 等量分箱 (pd.qcut)
print("\n=== pd.qcut 等量分箱 ===")
qcut_result = pd.qcut(data, q=4)
print(qcut_result.value_counts().sort_index())
import numpy as np
# 1. 创建有偏斜的数据(大部分值较小)
data = pd.Series([1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 20, 30, 40, 50])
print("=== 原始数据 ===")
print(data.values)
# 2. 等宽分箱 (pd.cut)
print("\n=== pd.cut 等宽分箱 ===")
cut_result = pd.cut(data, bins=4)
print(cut_result.value_counts().sort_index())
# 3. 等量分箱 (pd.qcut)
print("\n=== pd.qcut 等量分箱 ===")
qcut_result = pd.qcut(data, q=4)
print(qcut_result.value_counts().sort_index())
运行结果预期:
=== 原始数据 === [ 1 1 1 1 1 1 1 1 1 10 20 30 40 50] === pd.cut 等宽分箱 === (0.975, 13.25] 10 # 10 个值在这个区间 (13.25, 25.5] 1 (25.5, 37.75] 1 (37.75, 50.0] 2 # 2 个值在这个区间 dtype: 50 === pd.qcut 等量分箱 === (0.999, 7.75] 4 # 约 1/4 的数据 (7.75, 25.0] 4 (25.0, 42.5] 4 (10.0, 50.0] 4 # 约 1/4 的数据
代码解析:
pd.cut()将数据范围等分为 4 份,但由于数据高度偏斜,大部分值(9 个 1)落在第一个区间内。pd.qcut()确保每个区间包含相同数量的数据点(4 个),即使区间宽度差异很大。
提示:
pd.cut()适用于数据分布均匀或需要固定宽度区间的情况。pd.qcut()适用于数据分布不均或需要按排名/百分比划分的情况。

Pandas 常用函数