
pandas 这个库做过数据处理的人几乎天天离不开。我在项目里处理过几十万行的业务流水、清洗过字段混乱的导出表、也帮同事排查过各种“明明代码没错但结果不对”的诡异情况最后发现大部分问题都出在 pandas 基础不牢。这篇想跟你聊聊 pandas 最核心的数据结构、日常高频操作、文件读写和面试里真正会遇到的习题适合刚入门想系统打基础、或者已经在用但自觉基础不扎实的读者。读完你会发现很多所谓的高深技巧底层就是几个设计原则的灵活组合。pandas 解决的核心问题就一句话用 Python 处理结构化表格数据。你可能会说 Excel 也能做但当数据量上到几十万行、需要反复清洗和自动化处理时Excel 就力不从心了。pandas 提供了两个核心数据结构——Series和DataFrame所有操作都是围绕这两个结构展开。面试时问的那些loc和iloc的区别、dropna和fillna的取舍、merge和concat的使用场景本质上都是在考察你对这两个数据结构的理解深度而不只是背函数名。1. 先从为什么学pandas说起它能覆盖哪些场景1.1 你与Excel之间的差距就是pandas能补上的部分很多初学者会把 pandas 当成“用代码操作表格”的工具这个理解没错但太浅了。实际工作中 pandas 的价值体现在三个层面自动化、规模和灵活性。自动化很好理解同一个清洗流程写一次函数以后每次有新数据直接调用不用再手动拉公式、拖字段。规模指的是处理能力Excel 打开几十万行的数据就开始卡pandas 处理百万级记录仍然在秒级只要内存够。灵活性是 pandas 最有魅力的地方它可以把多个表格按条件关联merge、按维度聚合groupby、把长表转宽表pivot_table这一套操作在 Excel 里要么很难实现要么得写复杂的公式组合。我在实际项目中感受最深的一次是接手一个跨部门的业绩数据整合任务。三个系统导出的报表结构完全不同一个用 Excel 表格一个用 CSV一个直接是文本格式。用 pandas 统一读取之后先做字段对齐再做清洗和合并最后输出统一的汇总表整个流程不到两百行代码。这种场景下如果你只会read_excel和to_excel其实已经够用但如果你能理解 DataFrame 的索引机制和合并逻辑遇到字段对不上、数据重复、类型不一致这些坑时才能快速定位问题。1.2 环境准备pycharm安装pandas包超时的解决办法新手在 PyCharm 里装 pandas 时经常遇到connected time out或者下载速度极慢的情况。这个问题的根源是默认从官方 PyPI 源下载而官方源在国内访问不稳定。解决方式是换用国内镜像源。我推荐两种做法。第一种在 PyCharm 的Terminal里直接用 pip 命令并指定镜像pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple第二种更一劳永逸把默认源改成清华或阿里镜像pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple设置完之后再执行pip install pandas速度会快很多。这里有个细节想提醒你pandas 依赖numpy如果你先装了 pandas 再装别的科学计算包版本冲突是常见问题。我的习惯是新建虚拟环境时先统一安装用pip install numpy pandas openpyxl一次装齐。openpyxl是读写 xlsx 文件需要的引擎经常被忽略等报错提示Missing optional dependency openpyxl时才补装不如一开始就装上。注意如果你在公司内网环境有时候镜像源也可能不可达这时可以尝试离线安装——下载对应 Python 版本的.whl文件再用pip install xxx.whl本地安装。判断 Python 版本用python --version判断位数用 64 位还是 32 位不要下错。2. 数据结构是地基Series与DataFrame的设计逻辑2.1 Series一维数据别再用列表硬扛Series是 pandas 的一维数组结构你可以理解成一个带有标签的列表。它比 Python 原生列表强在两点一是可以用索引标签取值二是支持向量化运算。创建 Series 很简单import pandas as pd s pd.Series([10, 20, 30], index[a, b, c]) print(s[b]) # 20看到这里你可能会想这跟字典有什么区别区别很大。Series 的索引是可以重复的而且当你做运算时pandas 会按照索引对齐而不是按位置对齐s1 pd.Series({a: 1, b: 2}) s2 pd.Series({b: 3, a: 4}) print(s1 s2) # 结果按标签对齐a5, b5这个“索引对齐”的机制是 pandas 的底层灵魂。很多初学 pandas 的人在处理 DataFrame 时觉得莫名其妙的NaN出现了多半就是操作的两个表索引没有对齐。我建议你在学习阶段多花时间体会这一点它比背十个函数都有用。Series 的另一个实用操作是布尔索引筛选。比如s[s 15]会返回所有大于 15 的元素这在清洗数据时极其常用后面讲面试题时会再提到。2.2 DataFrame二维表创建与基本操作DataFrame是表格型数据结构由多个 Series 组成每一行有一个索引每一列有一个列名。创建方式最常见的三种从字典创建、从列表创建、从 NumPy 数组转换。import pandas as pd # 从字典创建每个键是一列 df1 pd.DataFrame({name: [张三, 李四], score: [88, 92]}) # 从列表创建每个列表是一行 df2 pd.DataFrame([[张三, 88], [李四, 92]], columns[name, score]) # 从 NumPy 数组转换 import numpy as np arr np.array([[1, 2], [3, 4]]) df3 pd.DataFrame(arr, columns[col1, col2])这三种方式最常用的是字典方式因为它更直观列名和数据类型在创建时就是确定的。这里补充一个实际经验从一个很大的 NumPy 数组转换 DataFrame 时最好显式指定columns否则生成的是数字列名后续操作很容易踩坑。DataFrame 的基本操作我列一个最常用的清单df.head()和df.tail()快速查看前后几行检查数据长什么样df.info()查看列名、非空数量、每列数据类型df.describe()数值列的统计摘要均值、标准差、分位数df.shape行数和列数df.columns列名面试和日常工作中df.info()是第一个应该执行的命令。很多数据问题比如某列本该是数字却显示object某列空值特别多在info()输出里一眼就能看出来。这是我在项目中反复验证过的习惯拿到一个未知数据集先head后info再做后续任何操作。注意df.shape是属性不是方法后面没有括号。很多人经常df.shape()报错这个错误在面试现场出现会非常尴尬平时就要注意。3. 数据类型转换与文件读写实操里最常被问的3.1 数据类型转换的细节与坑pandas 的数据类型和 Python 原生类型不完全一样。常见的类型有int64、float64、bool、object字符串居多、datetime64日期时间、category分类变量。面试常问的“pandas 数据类型转换”通常就是指astype()和pd.to_datetime()这两类。astype()是最直接的转换方式df[price] df[price].astype(float64) df[age] df[age].astype(int64) df[is_active] df[is_active].astype(bool)但astype()有两个常见坑。第一如果列里有无法转换的值如N/A会直接抛异常。这时候可以先清洗或者用pd.to_numeric(..., errorscoerce)——coerce的意思是转换不了的变成NaN随后再处理。第二在包含缺失值的列上转换整数会失败因为整数类型不能存NaN。解决办法是先fillna再转换。日期转换是最容易被忽视的。很多 CSV 里的日期是字符串比如2024-01-15如果不转换你没法做时间相关的筛选和计算。用pd.to_datetime()df[date] pd.to_datetime(df[date])转换完之后就可以用df[date].dt.year提取年份用df[df[date] 2024-01-01]做时间筛选。这里我踩过一个真实的坑如果数据里的日期格式是2024/01/15或20240115pd.to_datetime通常能自动识别但如果是15/01/2024这种日月年格式必须加参数format%d/%m/%Y否则会被误认为月日年导致数据错误。日期解析错了不会报错但结果错得非常隐蔽这也是为什么数据校验那么重要。3.2 读写CSV、Excel和文本文件参数选择比想象中重要文件读写是 pandas 最常用的功能但也恰恰是初学者最容易出错的地方。我几乎每周都会遇到同事拿着报错来找我一看就是编码问题或分隔符问题。读 CSV 文件df pd.read_csv(data.csv, encodingutf-8, sep,)编码问题是一个高频坑。很多老系统导出的 CSV 是 GBK 编码直接read_csv会报UnicodeDecodeError解决办法是把编码参数改成encodinggbk或者encodingutf-8-sig。如果连编码都不确定可以先用记事本打开文件看一眼或者用文本编辑器查看文件底部提示的编码信息。读 Excel 文件df pd.read_excel(data.xlsx, sheet_nameSheet1, engineopenpyxl)sheet_name可以传工作表名称也可以传索引0、1。如果 Excel 里有多个 sheet你可以一次读完pd.read_excel(data.xlsx, sheet_nameNone)会返回一个字典键是 sheet 名值是 DataFrame。这在处理多个结构相同的分月报表时特别好用。写文件同理df.to_csv(output.csv, indexFalse, encodingutf-8-sig) df.to_excel(output.xlsx, indexFalse, sheet_name结果)这里要重点强调indexFalse和encodingutf-8-sig这两个参数。indexFalse是为了不把索引列写进文件否则导出的数据会多一列0、1、2、3。encodingutf-8-sig是用于保证 Excel 打开 CSV 不会乱码——utf-8-sig会写入 BOM 头Excel 识别更友好。这些细节在面试中不一定会问但在实际项目中文件打不开、乱码、多列基本都是这几个参数没设置好。文本文件的读写本质和 CSV 类似区别在于分隔符可能是制表符\t或任意符号用sep指定即可。读取大文本文件时有chunksize参数可以分块读取而不会撑爆内存这是处理几个 G 级数据的必要手段。哪怕面试没问自己会这一招在实践场景里非常加分。4. ewm函数与进阶数据处理指数加权移动平均到底怎么用4.1 ewm参数全解析真正弄懂的人不多ewm是 pandas 里专门做指数加权移动平均的函数全称是 exponentially weighted moving average。它在金融时序分析、指标平滑、趋势识别中很常用。面试题里出现的频率不算特别高但一旦出现很多人会卡壳因为它的参数确实多。核心参数有三个span、halflife和alpha。它们描述的是同一件事的三种等价表示方式——给最近的数据更大的权重。alpha直接指定平滑系数取值范围 0 到 1越大表示越看重最近的数据span跨度alpha 2 / (span 1)常见取span10表示按 10 日窗口做平滑halflife半衰期表示权重衰减到一半所需的时间alpha 1 - exp(-ln(2) / halflife)举个例子模拟一只股票价格的日收益率波动用ewm做波动率平滑import pandas as pd import numpy as np np.random.seed(42) dates pd.date_range(2024-01-01, periods60, freqD) returns np.random.normal(0.01, 0.02, 60) # 模拟收益率数据 df pd.DataFrame({date: dates, return: returns}) # 计算指数加权移动平均span10 df[ewma_10] df[return].ewm(span10, adjustFalse).mean() # 用 alpha 方式效果等价 df[ewma_alpha] df[return].ewm(alpha2/(101), adjustFalse).mean()adjustFalse这个参数值得单独说。默认adjustTrue时ewm 会做更严格的归一化处理结果对序列前期的值平滑得更充分但过渡慢一点。设为False则直接用递推公式计算更贴近常规理解响应更快。选哪个看实际需求想做技术指标平滑adjustFalse是主流想要更平滑的历史平均效果用默认的True。ignore_na参数是另一个容易忽略的点。当序列中间有缺失值时默认算法会把缺失值的位置保留并影响权重计算。ignore_naTrue则表示忽略缺失值权重只按有效值递推。我的建议是先统一处理缺失值再去计算 ewm否则输出结果飘忽不定自己都解释不清楚。4.2 高频操作要练熟apply、merge、groupby的配合ewm 属于相对进阶的函数但真正撑起日常数据处理的是另外几个基础操作。面试题永远不会直接问你apply是什么而是给你一个场景考察你会不会用。我在这里把三个使用频率最高的操作串讲一遍。groupby加agg是最经典的聚合组合# 按部门分组分别统计人数、平均薪资、最大薪资 df.groupby(dept).agg( 人数(salary, count), 平均薪资(salary, mean), 最高薪资(salary, max) )merge用于按列关联两个表类似 SQL 里的joindf_orders.merge(df_customers, oncustomer_id, howleft)how参数决定保留哪些行left保留左表全部inner只保留两表共有的outer保留两表全部。实际业务中left用得最多因为你一般不想丢掉主表的记录。这里有坑如果关联的列名在两个表里不一样需要写left_on和right_on不要硬凑列名。还有一种常见错误是关联后数据量暴涨说明两侧表的关联列存在重复值产生了笛卡尔积匹配。排查方法是用df.duplicated()检查关联列的重复情况。apply用于对行或列逐条应用自定义函数df[category] df[score].apply(lambda x: 高分 if x 90 else 及格 if x 60 else 不及格)如果你在面试中被问到apply、map、applymap的区别记一个口诀map是 Series 的方法一个值映射成一个值apply是 DataFrame 的方法可以按行或列批量操作applymap是逐元素操作但现在官方更推荐用df.map()替代。这种题考的就是你看不看官方文档更新。5. pandas面试习题拆解常考题背后的考点是什么5.1 基础题loc与iloc、dropna与fillna面试问 pandas 的题目很多都是从“你是否真的用过而不只是看过”出发。举两个出现频率最高的。第一问loc 和 iloc 的区别是什么loc是按索引标签取值iloc是按整数位置取值。别小看这一句很多实际错误就出在这里。df pd.DataFrame({value: [10, 20, 30]}, index[a, b, c]) df.loc[a] # 按标签返回 10 df.iloc[0] # 按位置返回 10当你的索引是自定义的字符串或日期时loc才是正确的选择。而iloc更贴近 Python 的切片逻辑。两者的边界情况常常成为面试陷阱df.loc[a:b]是包含结束标签的df.iloc[0:1]则是不包含结束位置的。这一套规则和 Python 原生切片不一样不实际操作很难记住。我建议你自己写个小 DataFrame 试一下5 分钟能弄清楚。第二问dropna 和 fillna 怎么选处理缺失值是数据分析师的日常工作。dropna删除缺失行fillna填充缺失值。关键不在两个函数而在业务场景。缺失比例极低比如千分之一直接dropna不影响整体简单高效缺失比例较高但字段关键必须fillna用什么值填充取决于业务含义fillna的几种操作要记清楚df[col] df[col].fillna(0) # 填充固定值 df[col] df[col].fillna(df[col].mean()) # 用均值填充 df[col] df[col].fillna(methodffill) # 用上一个有效值填充已弃用改用 ffill() df[col] df[col].ffill() # 新写法前向填充用均值填充有争议——它会引入偏差。但对业务报表来说这往往比直接删行更可接受。如果你面试时能主动说出“我一般会先看缺失率再结合业务决定是填充还是删除”面试官会认为你有实际经验。5.2 进阶场景题去重、透视、超大文件进阶题考的不是函数本身而是你在复杂数据下的处理思路。我整理三个常见场景。场景一数据去重后保留哪条记录df.drop_duplicates(subsetuser_id, keepfirst)是按指定列去重keep控制保留哪一行。keepfirst保留第一次出现的行keeplast保留最后一次keepFalse删除所有重复行。很多面试官会追问“如果重复的记录字段值不一样你怎么决定保留哪条”这时候你不能只说函数应该说“先按业务时间排序再用drop_duplicates保留最新一条”这才是有经验的答法。场景二长表转宽表。pivot_table是高频考点。它的作用是按行和列两个维度重组数据配合聚合函数使用pd.pivot_table(df, valuesamount, indexmonth, columnsproduct, aggfuncsum, fill_value0)这个操作相当于 Excel 里的数据透视表。注意pivot_table必须指定aggfunc因为同一个行列组合下可能有多条数据。如果多个值返回时会给你一个聚合结果fill_value0是为了让空组合显示 0 而不是NaN。面试时被问到“pivot 和 pivot_table 的区别”答案就是pivot要求原始数据中行列组合必须唯一而pivot_table支持聚合更通用。场景三内存不够我处理一个大 CSV 怎么办这题有标准套路。第一用pd.read_csv(..., usecols[a, b])只读需要的列第二用dtypestr等设置节省内存的列类型第三用chunksize分块读取每块处理后合并结果第四实在不行就只读部分行试跑验证逻辑后再全量跑。只要你能说出第三点基本就能过关。因为大多数人的日常工作根本不会碰超大文件能列到分块处理这一层已经证明你不是只会读小文件。6. 常见报错与排查技巧实录6.1 高频报错速查表实战里报错是常态。我把自己这两年最常遇到的 pandas 报错整理成一张速查表遇到能少走很多弯路。报错信息原因解决方案UnicodeDecodeError: utf-8 codec cant decode读取 CSV 时编码不对改用encodinggbk或utf-8-sigMissing optional dependency openpyxl读取 xlsx 缺少引擎pip install openpyxlKeyError: xxx列名不存在检查是否拼错用df.columns确认ValueError: cannot reindex from a duplicate axis拼接时索引重复先df.reset_index(dropTrue)再操作SettingWithCopyWarning链式赋值操作的是副本改用df.loc[...] ...的写法TypeError: unsupported operand type(s)列类型是字符串却做数值运算先astype或pd.to_numeric转换Cannot convert non-finite values (NA or inf)含缺失值转整数失败先fillna再astypeSettingWithCopyWarning值得多说几句。它出现的时候代码通常还能跑只是警告但它背后是 pandas 的“视图 vs 副本”机制。你用链式写df[df[a]0][b] 1时pandas 没法确定你改的是原表还是副本于是发出警告。正确写法是统一用locdf.loc[df[a] 0, b] 1我见过不少项目因为忽略这个警告导致改数据没生效最后排查半天。建议从第一天起就养成用loc做条件赋值的习惯。6.2 我的实操心得与避坑经验最后分享几条只有长期用 pandas 才会总结出来的经验。第一拿到数据先做一份“体检”。我的固定流程是df.shape看规模df.head(5)看样子df.info()看类型和非空情况df.describe()看数值分布然后df.isnull().sum()精确统计缺失值。这套流程 30 秒执行完能避免后面 80% 的意外。第二写数据处理代码时每步都做一次结果验证。不要一口气写 50 行再运行。我自己的习惯是每处理完一个环节就print(df.shape)或者df.head(3)看一眼。判断逻辑对不对用形状变化和数据样例来验证比事后找 bug 高效十倍。第三不要忽视文件编码问题。这听起来太基础了但实际项目里几乎每个新接入的数据源都会在编码上出一次问题。我现在的做法是接新数据时先确认源文件编码统一用utf-8-sig输出时间长了能省非常多沟通成本。第四遇到 pandas 函数表现不符合预期时先查官方文档的“弃用说明”。pandas 版本迭代很快很多网上的老教程写法已经过时比如fillna(methodffill)在新版本里已经改成了ffill()。别迷信旧代码以你本地环境的版本为准。我个人在实际操作中还有一个体会pandas 的学习曲线其实不陡但坑是真的多。如果你能把每个报错都当成一次理解机制的契机而不是急着搜答案抄代码你的基础会扎实得多。练完这套基础再去做后面复杂的数据清洗、特征工程都会顺很多。完整学习下来题不在多核心是把Series、DataFrame、索引对齐、类型转换、文件读写这五件事吃透。它们就是 pandas 的地基地基稳了上面盖什么楼都不慌。