使用pd.cut按Code分组划分Qty类别时遇“bins需单调递增”错误求助
按分组累计Qty占比划分类别问题解决
原始数据
import pandas as pd df = pd.DataFrame({ 'Code': ['AAD', 'AAD', 'AAG', 'AAG', 'AAG', 'ALA', 'ALA'], 'Notes': ['2A 2K', '2A 1K', '2A 3K', '4A 4K', '5A 5K', '1A 2K', '1A 1K'], 'Qty': [17, 1, 12, 2, 1, 10, 3] })
错误原因分析
原代码报错bins must increase monotonically是因为定义的bins = [total*0.15,total*0.05,total*0.8]数值递减,而pd.cut要求bins必须单调递增。同时原逻辑存在两个核心问题:
- 未对每组内的
Qty按降序排序,无法保证数量大的条目优先划入高占比类别 - 阈值区间定义错误,未匹配“80%→class1,剩余15%→class2,其余→class3”的需求
正确实现方案
方案1:使用apply自定义函数划分类别
# 按Code分组,每组内按Qty降序排序 df_sorted = df.sort_values(['Code', 'Qty'], ascending=[True, False]).reset_index(drop=True) # 计算每组总Qty、累计Qty、累计占比 df_sorted['total_qty'] = df_sorted.groupby('Code')['Qty'].transform('sum') df_sorted['cum_qty'] = df_sorted.groupby('Code')['Qty'].cumsum() df_sorted['cum_pct'] = df_sorted['cum_qty'] / df_sorted['total_qty'] # 根据累计占比分配类别 df_sorted['Class'] = df_sorted['cum_pct'].apply( lambda pct: 'class1' if pct <= 0.8 else 'class2' if pct <= 0.95 else 'class3' ) # 整理结果列顺序 result = df_sorted[['Code', 'Notes', 'Qty', 'Class']] print(result)
方案2:分组使用pd.cut(修正bins顺序)
def process_group(group): # 组内按Qty降序排序 sorted_group = group.sort_values('Qty', ascending=False) total = sorted_group['Qty'].sum() # 定义单调递增的bins:0→80%总和→95%总和→无穷大 bins = [0, total*0.8, total*0.95, float('inf')] labels = ['class1', 'class2', 'class3'] sorted_group['Class'] = pd.cut( sorted_group['Qty'].cumsum(), bins=bins, labels=labels, right=False ) return sorted_group # 分组处理并合并结果 result = df.groupby('Code', group_keys=False).apply(process_group).reset_index(drop=True) print(result)
输出结果
Code Notes Qty Class 0 AAD 2A 2K 17 class1 1 AAD 2A 1K 1 class2 2 AAG 2A 3K 12 class1 3 AAG 4A 4K 2 class2 4 AAG 5A 5K 1 class3 5 ALA 1A 2K 10 class1 6 ALA 1A 1K 3 class2
内容的提问来源于stack exchange,提问作者beginner
相关产品推荐
相关产品推荐

