✍️
作者: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。
资源推荐
-
《利用 Python 进行数据分析》(Python for Data Analysis):Pandas 作者 Wes McKinney 亲笔,Pandas 的“圣经”,数据规整的思想一点不过时;
-
Pandas 官方文档:User Guide 和 Cookbook 是最好的学习材料,比任何第三方教程都准确权威;
-
Stack Overflow:遇到的 99% 问题都有人问过,学会用准确的英文关键词搜索是基本功。
写在最后
Pandas 的精髓,不在于记住多少函数,而在于建立一套以“数据规整”为核心、以“向量化”和“链式调用”为风格的思维模式。把这套心法刻在脑子里,去真实项目里摸爬滚打、踩坑、解决没人遇到过的问题,这些方法就会从你的“知识”变成你的“本能”。
到那时候,你就不再会问“Pandas 常用方法是什么”了——整个 Pandas 都成了你信手拈来的工具箱。