Pandas中使用整数区间作字典键映射列分值未生效如何解决
问题原因
Python原生字典的键匹配是精确哈希匹配,你定义的dict_reject_amount里,除了键0是整数类型,其余键全是range类型的对象。Series.map()做映射时,是拿列里的整数值去和字典键做相等判断,整数和range对象永远不可能相等,自然匹配不到对应分值,最终返回的结果全是空值NaN。
快速验证方式:随便取一个你预期能匹配上的整数,比如50,执行50 in dict_reject_amount,会直接返回False,就能确认匹配逻辑不成立。
修正方案
根据你的场景,优先选前两种方案,第三种仅做参考:
方案1:用pandas原生分箱函数pd.cut(推荐,性能最优)
针对固定区间映射分值的场景,pd.cut是pandas专门做这类分箱赋值的API,不用手写循环,大数据量下性能最好:
# 转整数的逻辑和你原有代码一致,无需修改 new['rejected_int'] = new['rejected'].astype(int) # 按你当前写的字典规则定义分箱边界,左闭右开区间和range的整数取值完全对齐 bins = [-1, 1, 101, 201, 301, 401, 501, 601, 701, 801, 901, 100000] scores = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9] new['reject_amount_points'] = pd.cut( new['rejected_int'], bins=bins, labels=scores, right=False ).astype(int)
如果你实际业务规则是0-100统一对应0分,直接调整
bins和scores即可,比如把前两个区间合并为[-1, 101],对应分值设为0。
方案2:自定义映射函数(适合规则灵活调整的场景)
如果后续区间规则可能频繁改动,可以写一个判断值所属区间的函数,传入map即可,逻辑直观好修改:
def calc_reject_score(val): if val == 0: return 0 rule_list = [ (range(1,101), 1), (range(101,201), 2), (range(201,301), 3), (range(301,401), 4), (range(401,501), 5), (range(501,601), 6), (range(601,701), 7), (range(701,801), 8), (range(801,901), 9), (range(901,100000), 9) ] for range_obj, score in rule_list: if val in range_obj: return score # 超出100000的兜底分值,可按业务需求调整 return 9 new['reject_amount_points'] = new['rejected_int'].map(calc_reject_score)
方案3:展开range为全整数键字典(不推荐)
你也可以把每个range里的所有整数展开,作为字典的独立键,这样就能满足map的精确匹配要求,但你当前的区间上限到100000,生成的字典会占用大量不必要的内存,数据量大时性能很差,仅适合区间范围极小的场景:
dict_reject_amount = {0: 0} range_rule = [ (1,101,1), (101,201,2), (201,301,3), (301,401,4), (401,501,5), (501,601,6), (601,701,7), (701,801,8), (801,901,9), (901,100000,9) ] for start, end, score in range_rule: for num in range(start, end): dict_reject_amount[num] = score new['reject_amount_points'] = new['rejected_int'].map(dict_reject_amount)
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

