最常用多级分类方法是pd.cut(固定区间)和pd.qcut(分位数),其次为np.select(多条件组合),需注意标签类型、顺序控制及避免apply性能陷阱。

用 pd.cut 或 pd.qcut 生成数值型多级分类标签
直接对连续数值列做分段打标,是最常见的多级分类需求。比如把销售额分成“低/中/高”三级,关键不是写 if-else,而是选对切分方式:
-
pd.cut按固定区间切分(适合业务定义明确的阈值,如bins=[0, 100, 500, 1000]) -
pd.qcut按分位数切分(适合数据分布不均时保证每级样本量接近,但要注意q=3不总能严格等分,尤其有重复值时会报ValueError: Bin edges must be unique - 务必传
labels参数显式指定标签名,否则返回的是区间对象,后续难以参与分组或绘图 - 示例:
df['sales_level'] = pd.cut(df['sales'], bins=[0,200,800,10000], labels=['low','mid','high'])
用 numpy.select 组合多个布尔条件生成非数值型多级标签
当分类逻辑涉及多个字段、混合类型判断(比如“VIP客户且近30天下单≥2次”),np.select 比嵌套 np.where 更清晰、更易维护:
- 条件列表和结果列表必须等长,且顺序严格对应;漏掉
default参数会导致未匹配行变成NaN - 条件表达式里避免直接写
df['a'] > 1 & df['b'] == 'x'——&优先级高于==,必须加括号:(df['a'] > 1) & (df['b'] == 'x') - 字符串标签建议统一用
str类型,避免混入None或np.nan导致astype('category')失败 - 示例:
conds = [(df['age']=18)&(df['age']=60)]; choices = ['minor','adult','senior']; df['age_group'] = np.select(conds, choices, default='unknown')
用 pd.Categorical.from_codes 手动控制多级标签顺序和缺失值行为
生成的分类标签默认是无序的,但做分组统计、画图(如 seaborn.barplot)时往往需要固定顺序(如“待审核→已通过→已拒绝”)。这时候不能只靠 sort=False,得用类别类型显式建模:
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 先用逻辑生成整数编码(0/1/2…),再用
pd.Categorical.from_codes映射为带顺序的类别,比df['status'].astype('category').cat.reorder_categories(...)更可控 - 如果原始数据含非法值(如空字符串、意外状态码),
from_codes会静默转成NaN,需提前用np.where过滤或设ordered=True后调用.remove_unused_categories() - 注意:
from_codes不接受负数编码,-1 会被当成缺失,别误用 -1 表示“未知”
避免 apply + 自定义函数生成标签——性能陷阱
有人习惯写 df.apply(lambda x: get_label(x['a'], x['b']), axis=1),这在万级数据下就明显变慢,十万级基本卡死:
-
apply是 Python 循环,无法利用 Pandas 底层向量化;同等逻辑用np.select或布尔索引通常快 5–50 倍 - 若逻辑真复杂到必须用函数,优先考虑
numba.jit编译或拆成多步向量化操作,而不是硬扛apply - 调试时容易忽略
axis=1导致函数接收的是 Series 而非标量,抛出KeyError或AttributeError
多级标签真正的难点不在生成动作本身,而在于后续如何让这些标签稳定参与分组、聚合、可视化。一旦用了 astype('category'),就得同步管理 categories 和 ordered 属性,否则 merge 或 concat 时可能意外丢失级别或打乱顺序。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










