如何用 pandas 实现自定义边界(含右闭区间)的数值分箱

8次阅读

如何用 pandas 实现自定义边界(含右闭区间)的数值分箱

本文介绍在 pandas 中对数值序列进行非均匀分箱时,如何精确控制最后一个区间的闭合性——特别是让 `[190, 200]` 成为右闭区间(包含 200),突破 `pd.cut` 默认左闭右开限制。

数据分析中,pd.cut 是最常用的分箱工具,但它默认所有区间均为“左闭右开”(如 [a, b)),即使设置 right=False 也仅将整体改为“左开右闭”(如 (a, b]),无法实现混合区间类型(例如前四段为 [a, b),最后一段为 [c, d])。当业务逻辑要求某特定值(如 200)必须被明确归入某个桶(尤其是作为右端点闭合)时,需结合布尔掩码进行后处理。

以下是一个完整、可复现的解决方案:

import pandas as pd  # 构造示例数据:100.0 到 200.3 的等距浮点数(含精确的 200.0) s = pd.Series(range(1000, 2004)).div(10)  # 100.0, 100.1, ..., 200.0, 200.1, ...  # 定义分箱边界(5 个间隔 → 6 个断点) bins = [100, 135, 160, 175, 190, 200] labels = ['[100, 135)', '[135, 160)', '[160, 175)', '[175, 190)', '[190, 200]']  # 第一步:用 pd.cut(left-closed, right-open)完成主体分箱 cut_result = pd.cut(s, bins=bins, labels=labels, right=False)  # 第二步:识别值恰好等于 200 的位置,并强制赋值为 '[190, 200]' mask_200 = s == 200.0 out = cut_result.mask(mask_200, '[190, 200]')  print(out.iloc[998:1003])  # 查看关键位置(含 199.9, 200.0, 200.1)

输出片段:

998    [190, 200] 999    [190, 200] 1000   [190, 200]   # ← 精确匹配 200.0,已正确归入闭区间 1001         NaN   # ← 超出最大边界,保持 NaN(合理) 1002         NaN

关键要点说明:

  • bins 必须严格递增,且长度比 labels 多 1;
  • right=False 确保前四段为 [a, b) 形式;
  • 使用 .mask(condition, value) 是安全覆盖的推荐方式(比 .loc[condition] = value 更健壮,尤其对 category 类型);
  • 对于超出 bins 范围的值(如 200.1),pd.cut 默认返回 NaN,符合预期,无需额外处理;
  • 若需将 200.0 映射为整数标签(如 4)而非字符串区间,可先用 pd.cut(…, retbins=False) 得到 codes,再单独修正 codes[s==200] = 4。

该方法简洁、高效、可扩展——若未来还需支持其他特殊点(如 100.0 强制归入首区间),只需增加对应布尔条件即可。

text=ZqhQzanResources