如何按客户属性(账户类型)分组计算数据集的十分位(Decile)排名
按账户类型计算分组十分位的实现方案
核心逻辑是按账户类型分组后,在每个组内部单独应用qcut计算十分位排名,不需要逐类手动过滤数据,用pandas自带的分组转换能力就能高效实现。
基础实现代码
# 替换代码中「账户类型列名」为你实际表中的客户属性列名称(比如acct_type) df['Decile_rank'] = df.groupby('账户类型列名')['bps_impact'].transform( lambda x: pd.qcut(x, 10, labels=False) )
代码逻辑说明:
groupby('账户类型列名')会把原表按照不同账户类型拆成独立的计算单元transform会把每个分组内的qcut计算结果,自动对齐回原表对应的行索引,不需要手动做分组结果的拼接匹配- 计算完成后每个行的Decile_rank,都是其所属账户类型组内的bps_impact十分位排名,完全符合按客户属性过滤的计算要求
常见场景的边界处理
- 分组样本量不足的报错处理
如果某类账户的样本总数少于10条,qcut会因为分箱数量超过样本量抛出错误,可以增加参数兼容这类场景:
这个参数会在遇到重复的分位边界时自动调整分箱宽度,避免因样本量不足中断计算。df['Decile_rank'] = df.groupby('账户类型列名')['bps_impact'].transform( lambda x: pd.qcut(x, 10, labels=False, duplicates='drop') ) - 需要校验分位边界的场景
如果需要留存每个账户类型对应的十分位切分阈值做后续审计,可以在计算时额外返回边界值:# 同时返回分位标签和对应的切分边界 group_decile_result = df.groupby('账户类型列名')['bps_impact'].apply( lambda x: pd.qcut(x, 10, labels=False, retbins=True) )
计算逻辑差异说明
和原有的全量qcut计算相比,分组计算的排名是组内独立排序:
- 全量计算:把所有账户的bps_impact混在一起排序切10档,不同账户类型的样本会互相挤占排名位
- 分组计算:每个账户类型内部从高到低切10档,组内前10%的样本打最高的9分,组内最低10%的打0分,排名结果不跨账户类型比较
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

