第七天:你用Excel做不了的,Pandas三行搞定
- 2026-09-18 08:50:46
每个月的1号,对在财务部工作的林岚来说,都像是一场逃不掉的劫难。早上九点,她准时打开邮箱,下载了六个不同区域发来的销售报表。格式略有不同,编码规则也有出入。她的任务是把这些表拼成一张全国总表,然后把退货率超过15%且销售额低于平均线的“问题单品”全部标红,最后按大区经理的维度生成一张汇总透视图。
这套流程她做了三年,熟练得让人心疼。打开Excel,复制、粘贴、VLOOKUP、筛选、删除重复项、数据透视表……一套组合拳下来,眼睛酸涩,手腕发僵。等她把所有颜色标好、公式检查完,抬头看表,已经是中午十二点半。下午两点开会,她连吃饭都得狼吞虎咽。
直到上周,她看着隔壁部门新来的同事,在不到三分钟的时间里,用一段黑底白字的代码完成了几乎同样的工作。那个同事甚至有时间泡了杯茶,然后慢悠悠地开始写会议发言提纲。
林岚第一次觉得,自己引以为傲的Excel“熟练工”身份,正在被某种更锋利的东西取代。那个东西,就是Pandas。今天这篇文章,不讲虚的,我们就用她经历过的四个真实场景,看看那些让你加班到深夜的Excel苦活,Pandas是如何用三行代码——甚至更少——直接掀翻桌子的。
一、合并六张表:告别“复制粘贴半小时”
观点:在Excel里合并多个结构相似的文件,本质是体力活;在Pandas里,这是一个被封装好的原子操作。
解释:很多人觉得VLOOKUP能解决一切,但VLOOKUP的前提是你已经把数据放进了一张表里。当你有六个、十六个甚至六十个文件时,Excel的“合并”功能要么不够灵活,要么需要你写复杂的Power Query步骤。而Pandas的pd.concat()函数,专门为这种“纵向堆叠”而生。它不管你传进去两个DataFrame还是两百个,只要列名对齐,一行代码直接融合。

案例:林岚之前处理六个区域的报表,最怕的是某个区域的列顺序跟别的不一样,或者多了一列备注。她得手动调整。用Pandas,她只需要把六个文件的路径放在一个列表里,然后用列表推导式一次性读取:
import pandas as pdfiles = ['华北.xlsx', '华东.xlsx', '华南.xlsx', '西南.xlsx', '西北.xlsx', '东北.xlsx']df_list = [pd.read_excel(f) for f in files]total_df = pd.concat(df_list, ignore_index=True)
建议:不要一次性把所有文件路径手动写死。学会用glob.glob('*.xlsx')自动抓取文件夹内所有Excel文件。这样下个月新增了一个“华中区”,你连代码都不用改,直接运行,自动合并。
二、复杂条件筛选:告别“筛选后复制再撤销”
观点:当筛选条件超过三个“且”或“或”的关系时,Excel的界面操作就开始变得反人类,而Pandas的逻辑运算符写出来就是自然语言。
解释:你想找“销售额低于区域平均线”且“退货率高于15%”的商品。在Excel里,你得先新建一列算平均线,再用辅助列判断布尔值,最后筛选TRUE。步骤繁琐,且一旦源数据刷新,辅助列容易出错。在Pandas里,你可以直接把判断条件写在一对括号里,用&(且)或|(或)连接,清晰到像在读句子。

案例:那天林岚需要筛选出所有“华北区”和“华东区”里,单价大于100元且库存小于50件的紧急补货清单。在Excel里,她先筛选大区,再筛选单价,再筛选库存,来回点了十几次鼠标。用Pandas:
target = total_df[(total_df['大区'].isin(['华北', '华东'])) &(total_df['单价'] > 100) &(total_df['库存'] < 50)]
两行,一目了然。更重要的是,这个筛选结果target是一个新的DataFrame,你可以直接对它进行下一步分析,而不用像Excel那样担心原表被破坏。
建议:把常用的筛选条件保存为Python变量。比如high_value = df['单价'] > 100,然后在复杂筛选时直接引用这些变量名,代码的可读性和可维护性会大幅提升。你的同事看你的代码,就像看一份检查清单。
三、分组聚合:比数据透视表更灵活
观点:Excel的数据透视表很强,但它是“所见即所得”,一旦布局固定,想换个维度看数据,就得拖拽字段重新生成。Pandas的groupby是“所写即所得”,你改一个字段名,结果全变。
解释:透视表擅长呈现二维的汇总结果,但如果你想同时求平均值、最大值、最小值,还要计算分组内的排名,透视表的“值字段设置”就显得笨重了。groupby配合agg()方法,允许你像搭积木一样,把你想对每一组做的所有运算,写在一个字典里一次性输出。

案例:林岚需要按“大区”和“商品类别”两个维度,计算总销售额、平均折扣率,以及该类别下最贵商品的单价。在透视表里,她要拖三次数值字段,再改三次值汇总方式。在Pandas里:
result = total_df.groupby(['大区', '商品类别']).agg(总销售额=('销售额', 'sum'),平均折扣=('折扣率', 'mean'),最高单价=('单价', 'max')).reset_index()
三行。而且这个result直接就是一张干净的二维表,可以无缝接入后续的可视化或导出流程,省去了在透视表结果上再做一次“复制-粘贴为数值”的麻烦。
建议:熟悉agg()函数里传入元组的写法——新列名=(原列名, 聚合函数)。这是Pandas中最优雅的“重命名+计算”一步到位的方式,能让你彻底告别在Excel里对着“列标签”改名字的琐碎。
四、错误值清洗:当Excel的IFERROR写到手软
观点:Excel里最让人崩溃的不是报错,而是报错后你要逐个单元格去处理。Pandas的fillna()和replace(),是真正意义上的“一键清洗”。
解释:导出的系统数据里,总有些阴魂不散的#N/A、#VALUE!或者莫名其妙的空格。在Excel里,你可能会用IFERROR包裹每一个公式,或者用“查找和替换”一次次处理。但Pandas把空值和错误值视为一等公民,提供了专门的方法链式处理。尤其对于那些因为除数为0导致的inf(无穷大),Pandas也能轻松识别并替换。

案例:林岚的那张总表里,有一列“增长率”,因为部分新品去年没有销量,分母为零,Excel里直接显示为#DIV/0!,导致整个VLOOKUP结果全是错误。她以往的做法是手动输入0,或者用IFERROR(原公式,0)。如果有上千行呢?用Pandas,她先把所有非数值错误转为NaN,然后统一填充:
# 将#DIV/0!等错误转为NaN,再填充为0total_df['增长率'] = pd.to_numeric(total_df['增长率'], errors='coerce').fillna(0)# 顺便把字符串两边的空格清掉total_df['商品名称'] = total_df['商品名称'].str.strip()
两行,处理完了她之前要花半小时核对的所有异常值。errors='coerce'这个参数是杀手锏,它会把任何无法转换的数字直接变为缺失值,然后你可以对缺失值进行统一处置,彻底避免Excel那种“红绿灯”式的错误提醒。
建议:养成在数据加载后的第一分钟,就运行一次df.info()和df.describe()的习惯。这会让你一眼看到哪些列有缺失值、哪些列数据类型不对。把清洗步骤写成一个独立的函数,以后凡是遇到类似结构的数据,直接调用,省下的时间远超你写那几分钟代码的功夫。
当你把上述四个场景连起来看,会发现Pandas做的不是“替代”Excel,而是“重构”了你和数据的对话方式。在Excel里,你的操作是离散的——点这里、拖那里、右键设置格式。你的脑子在想“下一步该点哪”,而不是“这堆数据想告诉我什么”。Pandas强迫你用变量名去思考:total_df、target、result,每一个变量都代表一个明确的业务阶段。
这带来了一个底层思维的转变:从“操作者”变成“流程设计者”。你不再是一个执行重复动作的手,而是写下规则、让计算机去跑腿的大脑。这也是为什么,用Pandas的人往往不觉得加班是常态,因为他们把“月报”变成了“运行一下脚本”。
最后,问一个值得我们共同反思的问题:在你的日常工作中,有哪些任务是“熟练到条件反射”,但仔细一想,其实毫无创造价值的? 试着把它写下来,那就是你明天打开Jupyter Notebook的起点。数据世界从来不缺苦劳,但更奖励那些用三行代码,把苦劳变成历史的人。