网信安考核实践:从央巡整改到数据安全风险闭环
2026/10/13 10:10:53
# -*- coding: utf-8 -*- """ 案例:员工年终奖核算 演示 map 与 apply 的典型用法 知识点: 1. Series.map(字典) —— 值映射,把部门别名统一成标准名称 2. Series.map(函数) —— 逐格文本清洗(全角转半角、去空格) 3. Series.apply(函数) —— 逐元素套用判断规则(绩效等级 -> 描述) 4. DataFrame.apply(函数, axis=1) —— 逐行跨列计算(算年终奖) 5. map 与 replace 的差异:map 未命中变 NaN,replace 未命中原样保留 运行后: 直接在控制台打印清洗与计算后的结果(无需 Excel 文件) """ import unicodedata import pandas as pd def build_data(): """构造一份“脏”数据:部门别名混用、姓名带空格与全角英文""" return pd.DataFrame({ "姓名": [" 张三", "李四 ", "Wang Wu", "赵六", "钱七"], "部门": ["技术", "研发部", "tech", "市场", "人事部"], "绩效": ["A", "B", "A", "C", "B"], "月薪": [20000, 15000, 30000, 12000, 18000], }) # 部门别名 -> 标准名称(以后新增别名只改这里) DEPT_MAP = { "技术": "技术部", "研发部": "技术部", "tech": "技术部", "市场": "市场部", "营销部": "市场部", "marketing": "市场部", "人事部": "人事部", "hr": "人事部", } # 绩效等级 -> 年终奖系数(月薪的倍数) BONUS_MAP = {"A": 3.0, "B": 2.0, "C": 1.0} def clean_name(x): """全角转半角 + 去首尾空格:'Wang Wu' -> 'Wang Wu'""" return unicodedata.normalize("NFKC", str(x)).strip() def perf_to_grade(p): """绩效字母 -> 中文描述""" if p == "A": return "优秀" elif p == "B": return "良好" else: return "待改进" def calc_bonus(row): """row 是整行(一个 Series),可同时读取‘绩效’与‘月薪’""" return round(row["月薪"] * BONUS_MAP[row["绩效"]], 2) def main(): df = build_data() # ---------- 1. map 用法①:字典映射,部门别名归一 ---------- df["部门"] = df["部门"].map(DEPT_MAP) # ---------- 2. map 用法②:传函数,逐格做文本清洗 ---------- df["姓名"] = df["姓名"].map(clean_name) # ---------- 3. apply 用法①:Series.apply,逐元素套复杂规则 ---------- df["绩效描述"] = df["绩效"].apply(perf_to_grade) # ---------- 4. apply 用法②:DataFrame.apply(axis=1),逐行算年终奖 ---------- df["年终奖"] = df.apply(calc_bonus, axis=1) print("===== 核算结果 =====") print(df.to_string(index=False)) # ====================================================================== # 课堂练习(题目) # ---------------------------------------------------------------------- # 练习1:把第 3 步的 apply 改成 map(lambda ...),验证结果是否相同。 # 练习2:把第 1 步的 map(DEPT_MAP) 改成 replace(DEPT_MAP), # 并让数据里出现一个映射表没有的部门,观察两者差异。 # 练习3:再加一列“综合评级”:绩效描述为“优秀”且月薪 >= 25000 # 记为“核心骨干”,否则为“普通员工”。 # ====================================================================== # ====================================================================== # 参考答案(讲课用,学生可先自行完成后对照) # ---------------------------------------------------------------------- # 练习1 参考: # df["绩效描述"] = df["绩效"].map(lambda p: "优秀" if p == "A" # else "良好" if p == "B" else "待改进") # # 结论:传函数时 map 与 apply 结果完全一致; # # 二者真正的差别在“能否直接吃字典”(map 可以,apply 不行)。 # # 练习2 参考: # s = pd.Series(["技术", "财务部"]) # “财务部”不在映射表里 # print(s.map(DEPT_MAP).tolist()) # ['技术部', nan] # print(s.replace(DEPT_MAP).tolist()) # ['技术部', '财务部'] # # 结论:map 未命中 -> NaN(可用来发现遗漏的别名); # # replace 未命中 -> 原样保留(做标准化更安全)。 # # 练习3 参考: # def level(row): # if row["绩效描述"] == "优秀" and row["月薪"] >= 25000: # return "核心骨干" # return "普通员工" # # df["综合评级"] = df.apply(level, axis=1) # # 结果:仅 “Wang Wu”(优秀且月薪 30000)被评为“核心骨干”。 # ====================================================================== if __name__ == "__main__": main()