22. apply 函数应用1. 概述apply()是 Pandas 中最强大的数据转换工具之一可以对 Series 的每个值或 DataFrame 的行/列应用自定义函数。它是向量化操作和循环之间的桥梁适用于复杂的数据转换逻辑。importpandasaspdimportnumpyasnp# 创建示例数据dfpd.DataFrame({姓名:[张三,李四,王五,赵六,钱七],年龄:[25,30,28,32,35],工资:[8000,12000,10000,15000,11000],绩效:[A,B,A,A,C],入职年份:[2019,2018,2020,2017,2021]})print(原始数据:)print(df)2. Series.apply()2.1 基本用法# 对单列应用函数df[工资_千元]df[工资].apply(lambdax:x/1000)print(工资转换为千元:)print(df[[工资,工资_千元]])# 使用自定义函数defgrade_to_score(grade):ifgradeA:return90elifgradeB:return80elifgradeC:return70else:return60df[绩效分数]df[绩效].apply(grade_to_score)print(\n绩效转分数:)print(df[[绩效,绩效分数]])2.2 使用外部参数# 带参数的函数defadjust_salary(salary,multiplier,bonus0):returnsalary*multiplierbonus df[调整后工资]df[工资].apply(adjust_salary,args(1.1,),bonus500)print(工资调整涨薪10%500:)print(df[[工资,调整后工资]])2.3 字符串处理# 使用 apply 处理字符串df[姓名_大写]df[姓名].apply(lambdax:x.upper())print(姓名转大写:)print(df[[姓名,姓名_大写]])# 复杂字符串处理defextract_info(name):returnf员工_{name}df[员工编号]df[姓名].apply(extract_info)print(\n生成员工编号:)print(df[[姓名,员工编号]])3. DataFrame.apply()3.1 按列应用默认 axis0# 计算每列的最大值print(每列最大值:)print(df[[年龄,工资]].apply(lambdax:x.max()))# 计算每列的范围print(\n每列范围:)print(df[[年龄,工资]].apply(lambdax:x.max()-x.min()))# 自定义聚合函数defcustom_range(x):returnf{x.min()}-{x.max()}print(\n每列范围字符串格式:)print(df[[年龄,工资]].apply(custom_range))3.2 按行应用axis1# 按行计算总分df[年龄工资]df.apply(lambdarow:row[年龄]row[工资]/1000,axis1)print(年龄 工资/1000:)print(df[[姓名,年龄,工资,年龄工资]])# 复杂行级计算defcalculate_bonus(row):baserow[工资]ifrow[绩效]A:returnbase*0.2elifrow[绩效]B:returnbase*0.1else:returnbase*0.05df[奖金]df.apply(calculate_bonus,axis1)print(\n计算奖金:)print(df[[姓名,工资,绩效,奖金]])3.3 行级条件判断# 多条件判断defget_level(row):ifrow[年龄]30androw[工资]10000:return优秀青年elifrow[年龄]30androw[工资]10000:return资深精英elifrow[年龄]30:return潜力新星else:return中坚力量df[人才标签]df.apply(get_level,axis1)print(人才标签:)print(df[[姓名,年龄,工资,人才标签]])4. apply 的高级用法4.1 返回 Series# 函数返回多个值defget_stats(x):returnpd.Series({最小值:x.min(),最大值:x.max(),平均值:x.mean(),中位数:x.median()})statsdf[[年龄,工资]].apply(get_stats)print(统计信息:)print(stats)4.2 使用参数 result_type# result_typeexpand 将列表结果展开为列defsplit_name(name):return[name[0],name[1:]]df[[姓,名]]df[姓名].apply(split_name,result_typeexpand)print(拆分姓名:)print(df[[姓名,姓,名]])4.3 条件 apply# 使用 apply 替代 np.wheredf[工资等级]df[工资].apply(lambdax:高ifx12000else(中ifx9000else低))print(工资等级:)print(df[[工资,工资等级]])5. apply 性能优化5.1 apply vs 向量化# 创建大数据集np.random.seed(42)large_dfpd.DataFrame({A:np.random.randn(1000000),B:np.random.randn(1000000)})importtime# 向量化操作最快starttime.time()large_df[C]large_df[A]large_df[B]print(f向量化耗时:{time.time()-start:.4f}秒)# apply 按列starttime.time()large_df[C]large_df.apply(lambdarow:row[A]row[B],axis1)print(fapply(axis1)耗时:{time.time()-start:.4f}秒)5.2 使用向量化函数# 尽量使用 NumPy 向量化函数df[年龄平方]df[年龄]**2# 向量化df[工资平方]np.power(df[工资],2)# NumPy 向量化# 避免在 apply 中使用 Python 循环6. 完整示例员工绩效评估# 创建员工数据np.random.seed(42)employeespd.DataFrame({姓名:[f员工_{i}foriinrange(1,21)],部门:np.random.choice([技术,销售,市场,人事],20),销售额:np.random.randint(50,500,20)*1000,完成率:np.random.uniform(0.6,1.5,20).round(2),满意度:np.random.uniform(3,5,20).round(1),工龄:np.random.randint(1,10,20)})print(*60)print(员工绩效评估)print(*60)print(\n原始数据:)print(employees.head())# 1. 计算绩效得分defcalc_performance_score(row):# 销售额得分0-50分sales_scoremin(row[销售额]/20000*50,50)# 完成率得分0-30分completion_scorerow[完成率]*20ifrow[完成率]1:completion_score10completion_scoremin(completion_score,30)# 满意度得分0-20分satisfaction_scorerow[满意度]*4# 工龄加分seniority_bonusmin(row[工龄]*2,10)totalsales_scorecompletion_scoresatisfaction_scoreseniority_bonusreturnround(total,2)employees[绩效得分]employees.apply(calc_performance_score,axis1)# 2. 评定等级defget_grade(score):ifscore90:returnSelifscore80:returnAelifscore70:returnBelifscore60:returnCelse:returnDemployees[等级]employees[绩效得分].apply(get_grade)# 3. 计算奖金defcalc_bonus(row):grade_multiplier{S:1.5,A:1.2,B:1.0,C:0.8,D:0.5}base_bonusrow[销售额]*0.05returnbase_bonus*grade_multiplier[row[等级]]employees[奖金]employees.apply(calc_bonus,axis1).round(0)# 4. 生成评估报告defgenerate_report(row):returnf{row[姓名]}-{row[部门]}- 得分{row[绩效得分]}-{row[等级]}级employees[评估报告]employees.apply(generate_report,axis1)print(\n绩效评估结果:)print(employees[[姓名,部门,销售额,绩效得分,等级,奖金]].head(10))# 5. 部门统计print(\n部门绩效统计:)dept_statsemployees.groupby(部门).agg({绩效得分:[mean,max,min],奖金:sum}).round(2)print(dept_stats)7. apply 与向量化对比方法速度适用场景向量化操作最快简单的算术运算NumPy 函数很快数学函数apply按列中等列级聚合apply按行较慢复杂行级逻辑循环最慢不推荐建议优先使用向量化操作无法向量化时使用apply。8. 总结用法说明示例Series.apply(func)对 Series 每个元素应用函数df[col].apply(lambda x: x*2)DataFrame.apply(func, axis0)按列应用函数df.apply(lambda x: x.max())DataFrame.apply(func, axis1)按行应用函数df.apply(lambda row: row[A]row[B], axis1)result_typeexpand展开列表结果df[col].apply(func, result_typeexpand)带参数传递额外参数df[col].apply(func, args(1,), extra2)