Python如何基于其他列取值动态调整Escalão列pd.cut分箱规则
实现pandas按其他列值动态分箱的方案
核心实现逻辑为:先预定义不同Produto、Zona维度组合对应的分箱规则,再对原始数据按对应维度分组,每组匹配对应的规则执行分箱操作即可。
1 修正原有代码语法问题
你现有测试代码存在几处语法错误,修正后如下:
import pandas as pd All = pd.DataFrame({ 'Master Agreement':['200011706.0','200011706.0','200011706.0','200011706.0','200011706.0','200011706.0'], 'Produto':['产品A','产品A','产品A','产品A','产品A','产品A'], # 补充你需要的Produto字段值 'Zona':['1','1','1','1','1','1'], 'Escalão':['200','300','900','100','120','240'], 'Peso Total':['233.830','343.977','507.750','400','230','110'] })
2 定义动态分箱规则
用嵌套字典存储所有维度组合对应的分箱参数,可根据业务需求自由扩展:
# 规则格式:(Produto取值, Zona取值) : {"bins": 分箱区间列表, "labels": 对应标签列表} bin_rules = { ("产品A", "1"): {"bins": [0,200,300,900, float("inf")], "labels": ["200","300","900","+"]}, ("产品A", "2"): {"bins": [0,150,400,800, float("inf")], "labels": ["150","400","800","+"]}, ("产品B", "1"): {"bins": [0,100,250,700, float("inf")], "labels": ["100","250","700","+"]} # 可继续补充其他组合的分箱规则 }
如果你不需要手动定义标签,期望直接取分箱区间的右边界作为标签,可省略规则中的labels配置,后续代码自动提取即可。
3 分组执行动态分箱
通过groupby+apply实现每个维度组匹配对应规则分箱:
手动定义标签版本
# 提前转换Escalão为数值类型,避免重复转换 All["Escalão"] = All["Escalão"].astype(float) def dynamic_cut(group): # 取当前组的维度值匹配规则 current_key = (group["Produto"].iloc[0], group["Zona"].iloc[0]) # 未匹配到规则时默认用产品A、Zona1的规则,可根据需求修改默认值 current_rule = bin_rules.get(current_key, bin_rules[("产品A", "1")]) group["Escalão de Peso dos Envios"] = pd.cut( group["Escalão"], bins=current_rule["bins"], labels=current_rule["labels"] ) return group All = All.groupby(["Produto", "Zona"], group_keys=False).apply(dynamic_cut)
自动取右边界作为标签版本
All["Escalão"] = All["Escalão"].astype(float) def dynamic_cut_auto_label(group): current_key = (group["Produto"].iloc[0], group["Zona"].iloc[0]) current_rule = bin_rules.get(current_key, bin_rules[("产品A", "1")]) cuts = pd.cut( group["Escalão"], bins=current_rule["bins"], include_lowest=True ) # 自动提取右边界为标签,无穷大值替换为"+" group["Escalão de Peso dos Envios"] = cuts.apply(lambda x: str(int(x.right)) if x.right != float("inf") else "+") return group All = All.groupby(["Produto", "Zona"], group_keys=False).apply(dynamic_cut_auto_label)
内容的提问来源于stack exchange,提问作者Daniela Rodrigues
相关产品推荐
相关产品推荐

