使用enumerate遍历pd.DataFrame列替换员工职级时出现长度不符问题及优化咨询
问题分析与解决方案
首先,咱们先找出你代码里导致结果长度不符的核心问题:
1. 错误的匹配逻辑导致重复添加
你在判断职级匹配时用了if df["lvl"][index] in v:,这里的in是包含匹配,而非精确匹配。举个例子,如果你的df["lvl"]里有值"2",它会匹配所有包含"2"的原职级键(比如"22"、"21"、"20"),每匹配一次就往r_levels里加一个值——这就导致单条数据被多次添加,最终结果列表长度远超原数据行数。
2. 完全没必要转字典为元组
你把字典转成元组的操作完全是绕远路,字典的核心优势就是通过键快速查找值,反过来遍历元组不仅效率低,还容易搞反映射关系(你转成的元组是(目标职级, 原职级),和原字典的键值方向相反)。
更简洁高效的解决方案
咱们直接利用字典的键值映射特性,结合pandas的内置函数来实现,既避免循环出错,又大幅提升效率:
方法一:用apply逐行处理(适合小数据量,逻辑直观)
import pandas as pd # 保留你原来的映射字典 lvls_sp = { "25":"1", "24" : "1", "23":"1", "22":"2" , "21":"2", "20":"3", "19":"3", "18":"3", "17":"3", "16":"4", "15":"4", "14":"5", "13":"5" , "12":"5", "11":"6", "10":"6", "9":"6", "8":"7", "7":"7", "6":"7", "0":"0" } lvls_uk = { "25": "s8", "24" : "s7h","23":"s7h", "22":"s7" , "21":"s7", "20":"s6","19":"s6", "18":"s6", "17":"s5", "15":"s4", "16": "s4", "14":"s3", "13":"s3" , "12":"s2h", "11":"s2", "10":"s2", "9":"s2", "8": "s2l" , "7": "s2l", "6": "s1", "0":"0" } # 定义映射函数,根据国家选择对应字典 def map_employee_level(row): # 先把职级转成字符串,确保和字典键类型匹配 lvl_str = str(row["lvl"]) if row["country"] == "SP": # 用get方法,找不到键就返回默认值"0" return lvls_sp.get(lvl_str, "0") elif row["country"] == "UK": return lvls_uk.get(lvl_str, "0") else: # 处理非SP/UK的情况,返回默认值 return "0" # 生成新的职级列 df["r_levels"] = df.apply(map_employee_level, axis=1)
方法二:用np.select+map(适合大数据量,效率更高)
如果你的数据集很大,apply的逐行处理会比较慢,推荐用numpy的select结合pandas的map:
import pandas as pd import numpy as np # 保留映射字典不变 lvls_sp = { "25":"1", "24" : "1", "23":"1", "22":"2" , "21":"2", "20":"3", "19":"3", "18":"3", "17":"3", "16":"4", "15":"4", "14":"5", "13":"5" , "12":"5", "11":"6", "10":"6", "9":"6", "8":"7", "7":"7", "6":"7", "0":"0" } lvls_uk = { "25": "s8", "24" : "s7h","23":"s7h", "22":"s7" , "21":"s7", "20":"s6","19":"s6", "18":"s6", "17":"s5", "15":"s4", "16": "s4", "14":"s3", "13":"s3" , "12":"s2h", "11":"s2", "10":"s2", "9":"s2", "8": "s2l" , "7": "s2l", "6": "s1", "0":"0" } # 转换职级为字符串,然后用map匹配对应字典的值,缺失值填充为"0" sp_mapped = df["lvl"].astype(str).map(lvls_sp).fillna("0") uk_mapped = df["lvl"].astype(str).map(lvls_uk).fillna("0") # 用np.select根据国家选择对应的映射结果 df["r_levels"] = np.select( [df["country"] == "SP", df["country"] == "UK"], [sp_mapped, uk_mapped], default="0" )
额外提醒
- 确保
df["lvl"]的类型和字典键的类型一致(都是字符串),如果你的lvl列是整数类型,一定要用astype(str)转换后再匹配,否则会因为类型不匹配找不到键,返回默认值0。 - 这两种方法生成的
r_levels直接是DataFrame的列,不需要再手动转成Series,更符合pandas的使用习惯。
内容的提问来源于stack exchange,提问作者alfonsosmdc
相关产品推荐
相关产品推荐

