✍️

作者:CodeCrafter | 来源:知乎 原文链接:https://www.zhihu.com/question/486515583/answer/1963287734132121742 著作权归原作者所有,转载仅供学习交流。

看到这个问题有点感慨。现在网上 Pandas 教程满天飞,动不动就是“十分钟入门 Pandas”“Pandas 100 个常用函数”。说实话,这种东西看看就得了,没啥大用——因为你记不住。

我带过不少新人,发现一个普遍问题:把 Pandas 当成一个需要“背诵”的库,今天学个 apply,明天学个 merge,学的时候好像会了,一到实际工作中,对着一堆乱七八糟的业务数据脑子还是一片空白,最后还是吭哧吭哧写 for 循环。

所以今天不搞函数清单式的罗列。聊聊我这小十年用下来、沉淀在肌肉记忆里、构成数据处理思维核心的那一套东西。它不是一堆函数,而是一个工作流和思维模式。掌握了这套心法,你才能从“知道 Pandas”变成“会用 Pandas”。

核心思想:忘掉花里胡哨,80% 的时间在“搓数据”

数据分析 80% 的工作,不是建模,不是调参,甚至不是可视化,而是枯燥、繁琐、但至关重要的数据清洗和规整。而 Pandas,就是你在这 80% 时间里最锋利的武器。你绝大部分的 Pandas 操作,都应该服务于一个目的:把一份“脏”的、原始的、不规则的数据,变成一份“干净”的、规整的、可以随时用于分析和建模的 Tidy Data。

什么是 Tidy Data?简单说,每行是一个观测,每列是一个变量。这是所有后续操作的基础。

第一阶段:拿到数据,先“望闻问切”

从数据库、CSV、Excel 搞来一份数据,第一件事绝对不是直接分析。跟中医看病一样,先搞清楚这份数据的“体质”。

1. 加载数据 read_xxx()

  • read_csv 里的 encoding:读中文报错十有八九是编码问题,试 encoding=‘utf-8’ 或 ‘gbk’;

  • parse_dates:某列是日期字符串,读取时直接 parse_dates=[‘列名’] 转成日期,省一步转换;

  • 数据量大时:用 nrows 先读几千行看情况,用 chunksize 分块读取避免内存爆炸。

2. “三板斧”快速探查

  • df.head(10):瞅前 10 行,列名对不对、有没有乱码;

  • df.info():个人认为最重要的命令。告诉你总行数、每列非空数量和数据类型。看到 Dtype 是 object 的列就要警惕——本应是数字的列却是 object,说明混了脏字符,这是清洗的重点信号;

  • df.describe():对数值列给 count/mean/std/min/四分位/max,快速发现异常值(年龄 max=200、价格 min 是负数都要查)。

第二阶段:定向打击,筛选与切片

记住一个原则:优先用 .loc 和 .iloc,尽量避免单独用 [] 做行列同时选择,容易产生误解和警告。

  • .loc:按标签(行索引名、列名)索引,最常用、最直观。选列用 df.loc[:, [‘列名1’,‘列名2’]];最强大的是布尔索引。

  • .iloc:按位置(从 0 开始的整数)索引。索引乱或只想取前几行时好用。df.iloc[:5] 取前 5 行,df.iloc[[0,2,4]] 取第 1/3/5 行。

布尔索引示例:

多个条件用 &(与)和 |(或),不能用 and/or,因为 df[‘city’]==‘北京’ 返回的是由 True/False 组成的 Series,不是单个布尔值。

总结:按列名和条件筛选用 .loc;按行号列号选就用 .iloc。刻在脑子里,99% 的筛选场景都能覆盖。

第三阶段:核心战场,数据清洗与转换

1. 处理缺失值:isnull / fillna / dropna

  • df.isnull().sum():统计每列缺失值数量;

  • df.dropna():删含缺失值的行/列,慎用。只在两种情况用:某行大部分为空;关键列(如 user_id)为空导致记录无效;

  • df.fillna():最常用。fillna(0) 填具体值,fillna(df[‘age’].mean()) 填均值,fillna(method=‘ffill’/‘bfill’) 向前/向后填充(时间序列很有用)。

2. 数据类型转换:astype / to_datetime

  • df[‘price’] = df[‘price’].astype(float):字符串转浮点;转换失败说明有非数字字符(如 ‘¥199’ 的 ¥),先用字符串方法清掉;

  • pd.to_datetime(df[‘order_time’]):专门处理日期时间,比 astype(‘datetime64[ns]’) 更强,能自动识别多种格式。

3. 字符串处理:.str 访问器

  • df[‘category’].str.contains(‘手机’):类别含“手机”的行;

  • df[‘ua’].str.split(’ ‘).str[0]:按空格拆分取第一段(浏览器名);

  • df[‘price_str’].str.replace(’¥’,’’).astype(float):典型清洗——去货币符号再转数字。

4. 创建新列 / 特征工程

这里引出三兄弟 apply / map / applymap:

  • apply():作用于 DataFrame 的行或列,灵活但慢;

  • map():只作用于 Series,做值映射,如 df[‘gender’].map({‘男’:1,‘女’:0});

  • applymap():作用于整个 DataFrame 的每个元素,用得较少。

一个忠告:能不用 apply 就不用。能用向量化操作(df[‘price’]*df[‘quantity’])就别用 apply 一行行算,向量化快得多。

微型实战:电商订单表算用户消费

场景:orders.csv 含 order_id、user_id、product_name、price、order_time,目标是算每个用户 2023 年的总消费和订单数。

这个例子把 info、str.replace、astype、to_datetime、.loc 布尔索引、dt 访问器和 groupby().agg() 全用上了——一个最基本但最常见的数据分析闭环。

第四阶段:分析的精髓,分组与聚合

  • df.groupby(‘分组列’):本身不显示内容,只创建 DataFrameGroupBy 对象,相当于把同组的行装进小盒子等你发号施令;

  • 简单聚合:df.groupby(‘city’)[‘salary’].mean(),sum/count/max/min 都适用;

  • 最强大的 .agg():对不同列同时用不同聚合函数。

groupby 的思想是 Split-Apply-Combine(拆分-应用-合并):groupby 拆分,agg 应用,Pandas 自动合并成新 DataFrame。

第五阶段:数据的整合,合并与连接

  • pd.concat([df_jan, df_feb]):理解为“堆叠”,两个表上下摞或左右拼,用于列结构相同的表(如 1 月和 2 月销售数据);

  • pd.merge():理解为 SQL 的 JOIN,按共同的键把两表横向连接。

on 指定连接键,how 指定连接方式:inner(默认)、left(最常用,保证左表完整)、right、outer。

思维进阶:从“能用”到“好用”

1. 向量化思维 > 循环 / apply 思维

这是区分新手和老手的核心标志。apply 底层是“伪循环”,把数据一个个交给 Python 解释器;向量化操作是把整列(底层 NumPy 数组)交给优化过的 C 代码,速度天差地别。

原则:发现自己在写 for 循环或复杂 .apply 遍历行时,立刻停下来想有没有向量化替代。

2. 链式调用(Method Chaining)

熟练后很多操作可以像链条一样串起来,省去一堆中间变量:

整个流程用 () 包起来,每步另起一行,从上到下逻辑清晰,没有中间变量污染,非常 Pythonic。

资源推荐

  1. 《利用 Python 进行数据分析》(Python for Data Analysis):Pandas 作者 Wes McKinney 亲笔,Pandas 的“圣经”,数据规整的思想一点不过时;

  2. Pandas 官方文档:User Guide 和 Cookbook 是最好的学习材料,比任何第三方教程都准确权威;

  3. Stack Overflow:遇到的 99% 问题都有人问过,学会用准确的英文关键词搜索是基本功。

写在最后

Pandas 的精髓,不在于记住多少函数,而在于建立一套以“数据规整”为核心、以“向量化”和“链式调用”为风格的思维模式。把这套心法刻在脑子里,去真实项目里摸爬滚打、踩坑、解决没人遇到过的问题,这些方法就会从你的“知识”变成你的“本能”。

到那时候,你就不再会问“Pandas 常用方法是什么”了——整个 Pandas 都成了你信手拈来的工具箱。