cut 按你给定的数值边界分组,qcut 按训练样本分位数分组,目标是按排序让各组数量相近。准备 AI 数值特征时,若业务已有明确阈值,用固定边界更好解释;若希望依据训练分布分层,可以考虑 qcut,但必须保存边界供新数据复用。
这里是用 pandas 完成特征离散化,不是让 AI 自动发现“最佳分组”。直方图只是展示分布,分箱则真的给每条样本赋予一个区间类别;训练矩阵的含义因此发生变化。

先明确端点属于哪组
本例训练数值为 0 至 11。固定区间采用 [0,4)、[4,8)、[8,12),因此 4 属于第二箱,8 属于第三箱。cut 默认右闭,这里明确 right=False,不能看边界数组相同就认为端点归属也相同。
qcut 示例分四组并返回真实边界。结果中最低区间标签可能为了包含最小值而显示略低于零的小数;保存和复用时使用 retbins 返回的数值数组,不从显示标签里复制或手工舍入。
0 至 11 及后面的重复值均为人为构造;本例只验证特征分组,不训练模型,不证明分箱会提高效果。实际环境是 Windows、Python 3.11.15、pandas 2.3.3、NumPy 2.4.6。
在空的练习目录里创建独立环境。以下为 Windows PowerShell 命令;macOS/Linux 的激活命令用 source .venv/bin/activate。输出文件只用于本次演示,重复执行会更新这些演示文件。
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install pandas==2.3.3 numpy==2.4.6
完整演示:边界、复用与重复值
保存为 feature_binning.py,执行 python feature_binning.py,先核对每箱数量与保存边界,再看新数据的分组。
import numpy as np
import pandas as pd
train = pd.Series(range(12), name='feature_value')
fixed = pd.cut(train, bins=[0, 4, 8, 12], right=False)
quantile, learned_edges = pd.qcut(train, q=4, retbins=True)
print('fixed_counts:', fixed.value_counts(sort=False).tolist())
print('quantile_counts:', quantile.value_counts(sort=False).tolist())
print('learned_edges:', learned_edges.tolist())
assert fixed.value_counts(sort=False).tolist() == [4, 4, 4]
assert quantile.value_counts(sort=False).tolist() == [3, 3, 3, 3]
assert np.allclose(learned_edges, [0, 2.75, 5.5, 8.25, 11])
new = pd.Series([-1, 0, 4, 11, 12], name='feature_value')
new_groups = pd.cut(new, bins=learned_edges, labels=False, include_lowest=True)
assert new_groups.isna().tolist() == [True, False, False, False, True]
assert new_groups.dropna().astype(int).tolist() == [0, 1, 3]
print('new_values:', new.tolist())
print('new_group_codes:', new_groups.tolist())
repeated = pd.Series([0] * 8 + [1] * 4)
try:
pd.qcut(repeated, q=4)
except ValueError:
print('duplicate_edges_rejected:', True)
else:
raise AssertionError('Repeated boundaries were accepted')
reduced = pd.qcut(repeated, q=4, duplicates='drop')
print('after_drop_number_of_bins:', len(reduced.cat.categories))
print('after_drop_counts:', reduced.value_counts(sort=False).tolist())
assert len(reduced.cat.categories) == 1
手算核对两种分组
fixed_counts: [4, 4, 4]
quantile_counts: [3, 3, 3, 3]
learned_edges: [0.0, 2.75, 5.5, 8.25, 11.0]
new_values: [-1, 0, 4, 11, 12]
new_group_codes: [nan, 0.0, 1.0, 3.0, nan]
duplicate_edges_rejected: True
after_drop_number_of_bins: 1
after_drop_counts: [12]
固定区间 [0,4)、[4,8)、[8,12) 每箱 4 条;qcut 的四个箱每箱 3 条,保存的边界为 0、2.75、5.5、8.25、11。每箱数量加起来都是 12,没有因分组丢掉训练记录。
新样本 -1、0、4、11、12 使用训练分位边界;0 进入第 0 组,4 进入第 1 组,11 进入第 3 组,-1 和 12 超范围,保持缺失。复用步骤采用 cut 默认右闭并设置 include_lowest=True,从而包含训练最小值 0。
输出组号以浮点显示,是因为同列还包含 NaN。0、1、3 是本例分组编号,不是新的测量值;不能直接把编号差解释为原数值差或业务风险差。供模型使用时,应按模型接口确定类别编码或其他表示,并保留箱的顺序与边界。
重复分位点不能静默处理
qcut 不能保证所有数据都能分成数量严格相等的指定箱数;大量重复值可能产生重复边界,必须明确处理。示例八个 0、四个 1 请求四分位箱,默认抛错;duplicates=”drop” 后只剩一个箱,12 条全在同一组。
这时不能继续在报告里写“四组比较”,也不能给减少后的组强行贴四个标签。先确认字段是不是常量或高度离散,再决定保留原类别、减少分组、改固定阈值或不分箱;这些选择需要业务含义与独立验证。
训练和预测怎样使用同一套边界
只在训练部分计算 qcut 边界,连同字段名、单位、闭区间规则、空值政策和类别映射一起保存。验证和新数据使用保存的数组调用 cut,不要每批重新 qcut;否则“第 1 组”在不同批次可能对应不同范围。
范围外的数据应先作为越界记录回查,本文不自动扩箱或剪裁。若决定使用负无穷与正无穷覆盖尾部,应先明确分组含义并重新验收边界;不能为了消除 NaN 临时改变在线规则。
如果只想观察原始分布而不改变特征,可先画直方图或 ECDF。若正式比较分箱与原特征的模型效果,应在同一数据划分与指标下评估,把边界拟合留在训练部分,不能用验证集重新选择分位点。
官方资料
以下资料实际读取于 2026 年 10 月 1 日;接口或界面范围按正文注明的版本核对。
Ai菜鸟网。发布者:AI小管家,转载请注明出处:https://www.alyyhw.com/32736.html