Python数据分桶方法_cut与qcut区别说明【教程】

业务规则固定时用pd.cut,按指定数值边界分组;需样本量均衡时用pd.qcut,按分位数等频分组;二者输出均为Categorical但逻辑不同,处理重复值、极值等需手动干预。

什么时候该用 pd.cut?看业务边界是否固定

如果你的分组标准来自外部规则(比如“0–60 不及格、60–85 及格、85–100 优秀”),或者数据天然有明确阈值(如年龄分段:0–18 未成年、18–60 成年、60+ 老年),pd.cut 是唯一合理选择。它按你给的数值边界硬切,不看数据分布。

  • 传入 bins 为列表(如 [0, 60, 85, 100])时,严格按左闭右开(默认 right=True(0, 60])或左开右闭(设 right=False[0, 60))划分
  • 传入 bins 为整数(如 bins=5)时,会等宽切分:(max - min) / 5 作为每个箱宽度,边界由数据极值决定,结果可能不符合业务直觉
  • 容易踩坑:未设 include_lowest=True 时,最小值可能被划到 NaN 箱(尤其当 bins 是整数且数据含极小值)

什么时候必须用 pd.qcut?看样本量是否要均衡

当你需要“每组人数差不多”,比如做用户分层运营(Top 10% 高价值用户、中间 80%、Bottom 10%)、或训练模型前强制平衡类别分布,pd.qcut 才是解法。它不管数值差多少,只保证每箱含大致相等数量的样本。

  • 核心参数是 q(如 q=4 表示四分位数,即分成 4 组),不是 bins
  • 若数据有大量重复值(如大量 0 或集中于某区间),qcut 可能报 ValueError: Bin edges must be unique —— 这时得先去重或改用 cut + 自定义边界
  • 返回的区间边界是反算出来的分位点(如 25%、50%、75% 分位数),所以每箱宽度不同;对偏态数据(如收入、点击率)更鲁棒

cutqcut 的输出类型与后续处理差异

两者都返回 Categorical 类型,但底层逻辑不同,影响 value_counts() 和绘图行为:

  • cut 输出的区间标签是确定的字符串(如 (60, 85]),可直接用于分组聚合或 map 映射业务含义
  • qcut 输出的区间标签默认是浮点范围(如 (2.345, 6.789]),精度高但难读;建议加 labels=False 得到整数编码,或手动传入 labels=['Q1', 'Q2', 'Q3', 'Q4']
  • 若后续要用 groupby 做统计,qcut 分箱后各组频次接近相等,而 cut 分箱后常出现“头重脚轻”(如大部分数据挤在中间一箱)

一个真实易错场景:用 qcut 分 10 组却只得到 9 个非空箱

这不是 bug,是预期行为。当数据量不能被整除(如 99 条数据分 10 组),qcut 会尽力让每组样本数相差 ≤1;但若存在大量重复极值(如 20 个 0 和 20 个 100),分位点会坍缩,导致某些箱无数据。

  • 验证方法:运行 qcut.value_counts().sort_index(),看是否出现 0 计数的箱
  • 解决办法:先检查数据分布(data.describe() + data.nunique()),若重复值占比高,优先用 cut + np.linspace 构造均匀边界,或用 qcut(..., duplicates='drop')(pandas ≥ 1.5.0)跳过重复分位点
  • 注意:duplicates='raise'(默认)会直接报错,'drop' 才静默跳过 —— 很多人卡在这一步没看到文档说明

实际分箱没有银弹。业务规则强就选 cut,数据分布歪就靠 qcut,而真正麻烦的永远是那 10% 的边缘情况:重复值、缺失值、极值、样本量不足——这些不会自动消失,得手动 inspect。