尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Pandas数据分析速成:从数据清洗到分组聚合与可视化

Pandas数据分析速成:从数据清洗到分组聚合与可视化 处理数据分析任务时很多人第一反应是打开 Excel 或者写一段 Python 脚本。Pandas 数据分析之所以在 Python 生态里占据核心位置是因为它把“表格数据的读取、清洗、筛选、分组、聚合、连接、透视、可视化”这条链路压缩到了几行代码以内。本文不打算把 Pandas 官方文档重新抄一遍而是按 2 小时速通的标准把最常用、最高频、面试和实际项目中最容易碰到的操作串成一条主线。学完之后你能独立完成一次从 CSV 读取到清洗、从分组统计到图表输出的完整数据分析流程。这套内容适合以下读者已经会一点 Python 基础语法但没系统用过 Pandas或者用过 Pandas 但只停留在df.head()和df.describe()层面遇到缺失值、类型转换、多表关联时容易卡住。本文会从数据结构讲起逐步进入数据读写、清洗、筛选、分组聚合、连接合并、可视化和常见坑排查每个环节都带可运行代码和预期输出。项目里的示例数据都是可复现的不需要额外准备数据集。1. 先理解 Pandas 的核心数据结构再谈数据操作1.1 Series 和 DataFrame 到底解决了什么问题Pandas 数据分析的最小单元是 Series 和 DataFrame。Series 可以理解成一列带索引的数据DataFrame 可以理解成多列 Series 组成的二维表。很多新手直接学操作方法忽略了这两个结构背后的设计逻辑结果遇到“索引错位”“类型变了”“合并结果多出重复列”这类问题时完全没有排查思路。先看一个最小示例import pandas as pd # Series一列数据默认索引为 0,1,2... s pd.Series([10, 20, 30], namescore) print(s) # DataFrame多列数据 df pd.DataFrame({ name: [张三, 李四, 王五], score: [10, 20, 30], city: [北京, 上海, 广州] }) print(df)运行后Series 会输出带索引的列DataFrame 输出一个完整的二维表。这里的核心理解点在于DataFrame 的每一列都是一个 SeriesSeries 的索引负责对齐数据和标签。很多操作报错本质上都是索引没有对齐或者索引重复导致的。1.2 索引、列名、dtype 是三个需要时刻关注的状态处理数据时不要只看数据内容。建议每次拿到一个 DataFrame先检查三个东西索引是什么样的、列名是什么样的、每一列的 dtype 是什么样的。下面的代码用来快速体检print(df.index) # 索引对象 print(df.columns) # 列名对象 print(df.dtypes) # 每列的数据类型 print(df.shape) # 行数和列数 print(df.info()) # 列名、非空数量、dtype 一网打尽这里有一个非常关键的判断Pandas 的 dtype 和 Python 原生类型不是一回事。object类型通常代表字符串或者混合类型int64和float64是数值类型datetime64[ns]是时间类型category是分类类型。实际项目里最常出现的问题是读入 CSV 后数字列变成了object时间列变成了字符串。如果不在分析前修正 dtype后面做求和、排序、时间筛选时就会出现各种奇怪报错。1.3 为什么 DataFrame 的很多操作要强调“返回新对象”Pandas 里大量操作比如drop、fillna、astype默认返回新对象不会修改原 DataFrame。很多新手写出如下代码后发现原表没变df.dropna() df.head() # 缺失值还在原因就是dropna()返回了新的对象但你没有把它赋值回去。正确写法是df df.dropna()或者使用inplaceTrue参数直接修改原对象。注意inplaceTrue并不是所有场景都推荐它的设计初衷是节省内存但在链式操作里很容易写出阅读性差的代码。建议明确赋值保持数据流清晰。理解这一点能避免大量“代码没生效”的问题。2. 环境准备Pandas 安装、版本选择和 IDE 配置2.1 确认 Python 版本与 Pandas 版本匹配Pandas 是一个频繁更新版本库的第三方包安装前最好先确认当前 Python 版本和 Pandas 版本是否兼容。以 Python 3.10 为例常见的兼容做法是安装 Pandas 1.5.x 或 2.x 版本。不同版本对 NumPy 的最低版本要求也不同只要保证 Python 和 Pandas 都是较新版本通常不会有太大问题。这里给出一种稳妥的安装方式使用 pip# 先升级 pip python -m pip install --upgrade pip # 安装 pandas会自动安装 numpy 等依赖 pip install pandas # 查看版本 python -c import pandas; print(pandas.__version__)如果网络环境比较慢可以指定国内镜像安装关于镜像配置不在本文展开。安装完成后强烈建议同时安装 openpyxl因为 Pandas 读写 Excel 的.xlsx格式依赖它pip install openpyxl2.2 PyCharm 中安装 Pandas 的两种方式PyCharm 用户可以在终端里直接执行 pip 命令也可以在设置里操作。这里多说一句在 PyCharm 里最关键的避坑点是先确认解释器选对了。如果项目使用的是虚拟环境终端里的 Python 和 PyCharm 配置的解释器不一致pip 安装的 Pandas 在当前项目里会找不到。在 PyCharm 的终端里执行以下命令# 确认当前解释器路径 python -c import sys; print(sys.executable) # 安装 pandas pip install pandas如果终端里的解释器路径与 PyCharm 项目解释器一致安装后直接可用。另一种方式是在 Settings - Project - Python Interpreter 里点击加号搜索 pandas 后安装。这种方式适合不喜欢敲命令的读者但要注意观察安装日志避免版本冲突。2.3 Jupyter Notebook 和脚本文件分别适合什么阶段速学阶段建议先使用 Jupyter Notebook因为它能按单元格逐步看到中间结果非常适合理解筛选、清洗、转换这类操作。等逻辑跑通后再整理成.py脚本文件用于自动化执行。实际项目中数据处理通常以脚本方式运行时需要额外加入print()或日志输出来确认每一步的结果否则脚本静默执行后出现问题不好定位。3. 数据读写从 CSV、Excel 到 SQL先解决“数据怎么进来”3.1 read_csv 的参数不要只记住文件路径read_csv是使用频率最高的数据读取函数。很多教程只写pd.read_csv(data.csv)但真实项目里 CSV 文件的编码、分隔符、表头情况千差万别。下面的代码展示了几个常用参数import pandas as pd # 常见场景文件带表头、utf-8 编码 df pd.read_csv(sales.csv, encodingutf-8) # 常见场景文件没有表头需要手动指定列名 df pd.read_csv(sales_no_header.csv, headerNone, names[order_id, amount, date]) # 常见场景分隔符不是逗号 df pd.read_csv(sales.tsv, sep\t) # 常见场景日期列先解析成时间类型 df pd.read_csv(sales.csv, parse_dates[order_date])这里最重要的参数是parse_dates。如果你读入的数据包含时间列建议在读取阶段就指定避免后面再手动转换。3.2 to_csv 和 to_excel 写出时的关键细节写出数据时最常见的问题是索引列被写成文件里的第一列导致下游程序读取时多出一列无意义的Unnamed: 0。解决办法是设置indexFalsedf.to_csv(result.csv, indexFalse, encodingutf-8-sig) df.to_excel(result.xlsx, indexFalse, sheet_nameresult)编码方面encodingutf-8-sig是为了让 Excel 打开 CSV 时不出现中文乱码。如果使用utf-8CSV 在 Excel 里打开时中文可能变成乱码而用记事本或 Python 读取是正常的。这是 Windows 环境非常常见的坑。3.3 兼容 Spark 场景的 parquet 和 feather 格式热搜词里有一个比较有意思的方向pandas与numpy实现spark在格式parquet及语言feather等上的案例操作。实际项目中大数据平台经常用 Spark 产出 parquet 格式的中间结果本地分析时可以直接用 Pandas 读取不用转 CSV。Pandas 读写 parquet 需要 pyarrow 或 fastparquetpip install pyarrow然后就可以# 读取 parquet df pd.read_parquet(data.parquet) # 写出 parquet df.to_parquet(result.parquet, indexFalse) # feather 格式 df pd.read_feather(data.feather) df.to_feather(result.feather)parquet 是列式存储格式文件小、读写快带类型信息适合作为中间结果。feather 更轻量适合同一机器上的快速读写。这两种格式比 CSV 更利于保留 dtype减少重复的类型转换工作。如果只是本地学习优先用 CSV 就够了如果接触大数据项目要尽早习惯 parquet。4. 数据清洗缺失值、重复值、类型转换和文本清理4.1 先检查缺失值再决定删除还是填充缺失值处理没有统一答案取决于业务场景。先看缺失情况# 每列的缺失值数量 print(df.isnull().sum()) # 缺失值的行 print(df[df.isnull().any(axis1)])any(axis1)表示“只要这一行里任意一列是缺失值就保留这一行”。如果你只需要看某列为空的行可以写print(df[df[amount].isnull()])删除缺失行和填充缺失值是两种最常见策略# 删除任意包含缺失值的行 df_drop df.dropna() # 删除指定列包含缺失值的行 df_drop_subset df.dropna(subset[amount]) # 用固定值填充 df_fill df[amount].fillna(0) # 用均值填充 df_fill_mean df[amount].fillna(df[amount].mean()) # 向前填充 df_fill_ffill df[amount].fillna(methodffill)注意Pandas 2.x 中fillna(methodffill)的写法和旧版略有区别新版推荐直接使用df[amount].ffill()。填充分为业务填充和统计填充两种思路业务填充需要知道“缺失值代表什么”统计填充则关注分布。不要无脑删除也不要无脑填 0。4.2 重复值要区分“完全重复”和“关键列重复”热搜词里有一条“pandas如果指定两列的值均相同,则取第一条数据即可”。这其实就是去重的典型需求。完全重复的行可以用df df.drop_duplicates()指定部分列去重保留第一条df df.drop_duplicates(subset[user_id, order_date], keepfirst)keep参数有三个常用值first保留第一条last保留最后一条False删除所有重复行。这里需要思考的是“重复”的业务含义一个订单里user_id和order_date相同是重复数据还是真实的多笔订单如果业务上两列相同就只保留一条说明它们能唯一标识一条记录如果不能就不应该按这两列去重。先把唯一键想清楚再写去重逻辑。# 查看重复行 print(df.duplicated(subset[user_id, order_date]).sum())4.3 数据类型转换astype 和 pd.to_datetime 的使用边界Pandas 数据类型转换是高频操作。最常见的场景包括字符串数字转数值、数值转字符串、字符串转时间。先看基础用法# 字符串转数值errors 参数控制错误处理 df[amount] pd.to_numeric(df[amount], errorscoerce) # 数值转字符串 df[user_id] df[user_id].astype(str) # 字符串转时间 df[order_date] pd.to_datetime(df[order_date])errorscoerce的含义是遇到无法转换的值时将其设置为缺失值NaN而不是直接报错。这样做的价值在于转换失败不会导致整个程序崩溃但后续处理要额外关注缺失值。astype和pd.to_numeric的区别在于astype遇到无法转换的值会直接抛异常pd.to_numeric配合errors参数更灵活。时间转换优先使用pd.to_datetime因为它能自动解析多种格式比astype可靠得多。日期列处理完成之后才能做时间筛选和按时间聚合。实际项目中时间列的类型错误往往隐藏很深比如月份列、日期列、带时分秒的列混在一起建议先统一格式再进入下一步。# 只取日期 df[date_only] df[order_date].dt.date # 取年月 df[year_month] df[order_date].dt.to_period(M) # 按时间筛选 df df[df[order_date] 2026-01-01]4.4 字符串列的清理操作文本数据里经常出现空格、大小写不一致、前缀后缀多余字符等。基础操作如下df[city] df[city].str.strip() # 去掉首尾空格 df[city] df[city].str.lower() # 转小写 df[city] df[city].str.replace(省, ) # 删除特定字符 df[is_bj] df[city].str.contains(北京) # 是否包含指定字符使用.str访问器之后字符串列的行为更像数组不再像裸 Python 字符串。新手最容易在这出错直接对整列调用.strip()结果报错说 Series 没有strip方法。记住凡是需要逐元素处理字符串都要先加.str。5. 数据筛选与索引loc、iloc、布尔条件怎么配合5.1 loc 按标签取值iloc 按位置取值很多人的痛点在于搞不清loc和iloc。简单来说loc根据索引标签和列名取值。iloc根据整数位置取值。# 取第一行 df.iloc[0] # 取前五行 df.iloc[:5] # 取某一行某几列 df.loc[0, [name, score]] # 行索引从 0 到 2列位置从 0 到 1 df.iloc[0:3, 0:2]更准确地说loc和iloc都支持行列两个维度写法是df.loc[行条件, 列条件]。如果只写一个维度默认取行。推荐在正式代码里优先使用loc因为它不受列位置变化影响语义更清晰。操作写法使用场景按位置取前 5 行df.iloc[:5]快速预览数据按索引标签取行df.loc[5]索引有意义时按条件取行df.loc[df[age] 30]条件筛选最常用取指定列df[[name, score]]列名准确时连续切片df.iloc[1:4]按位置滑动窗口5.2 布尔索引是筛选的核心能力布尔索引指的是用一串 True/False 序列作为行的筛选条件。最简单的写法# 筛选成绩大于 60 的行 df_filtered df[df[score] 60] # 多个条件用 和 | df_filtered df[(df[score] 60) (df[city] 北京)] # 属于某个集合 df_filtered df[df[city].isin([北京, 上海])]三个容易踩的坑第一个多个条件必须用而不是and。Python 的and作用于整个布尔结果无法对 Series 逐元素判断。第二个每个条件都要加括号否则运算符优先级会出错。第三个isin是最被低估的方法遇到“是否在列表 A 中”这种问题时效率比循环快得多。# 想要排除某个集合加 ~ df_filtered df[~df[city].isin([北京])]5.3 索引重置、排序和 sample 抽样数据筛选后索引可能变得不连续。如果不希望索引影响后续合并可以重置df_filtered df_filtered.reset_index(dropTrue)排序也是分析前的常见操作# 按一列升序 df_sorted df.sort_values(score) # 按多列一列升序一列降序 df_sorted df.sort_values([score, age], ascending[True, False])随机抽样在探索数据时很实用# 随机抽 5 行 df_sample df.sample(n5, random_state42) # 按比例抽样 df_sample df.sample(frac0.1, random_state42)random_state固定随机种子保证结果可复现。做数据分析项目时随机抽样、按比例拆分训练集和测试集都离不开它。6. 分组聚合与透视表从明细数据到统计结果6.1 groupby 的核心逻辑是“拆分-应用-合并”groupby是 Pandas 数据分析里最重要的方法之一。它的执行过程可以拆成三步根据分组列拆分数据。对每个组应用聚合函数或自定义函数。把每个组的结果合并成新的 DataFrame。先看最简单最常用的写法# 按城市分组计算销售额均值 result df.groupby(city)[amount].mean() print(result) # 按城市分组多列多个统计量 result df.groupby(city)[amount].agg([mean, sum, count]) # 指定多个聚合函数返回 DataFrame result df.groupby(city).agg( total_amount(amount, sum), avg_score(score, mean), cnt(order_id, count) ).reset_index()第三种写法是推荐写法。它可以一次命名汇总结果的列名避免结果列名是默认的mean、sum也方便后续继续使用。6.2 agg 比直接调用 mean 或 sum 更灵活直接调用df.groupby(city)[amount].mean()写法简单但只能做一次聚合。agg可以用列表或字典指定多个聚合方式# 对一列做多种统计 result df.groupby(city)[amount].agg([sum, mean, max, min]) # 对不同列做不同统计 result df.groupby(city).agg( total_amount(amount, sum), avg_score(score, mean), orders(order_id, count) )agg的另一个价值是支持自定义函数。虽然自定义函数性能一般但遇到特殊逻辑时很实用result df.groupby(city)[amount].agg( totallambda x: x.sum(), rangelambda x: x.max() - x.min() )6.3 pivot_table 实现透视表效果如果你熟悉 Excel 数据透视表Pandas 的pivot_table使用逻辑几乎一致。它解决的问题是“把行维度转成列维度”从而观察不同维度之间的交叉关系。import pandas as pd df pd.DataFrame({ city: [北京, 北京, 上海, 上海, 广州], product: [A, B, A, B, A], amount: [100, 200, 150, 250, 300] }) pivot df.pivot_table( indexcity, columnsproduct, valuesamount, aggfuncsum, fill_value0 ) print(pivot)结果会变成城市为行、产品为列、金额为值的交叉表。fill_value0的意思是没有出现过的组合用 0 填充。透视表适合快速观察分类变量之间的关系也是面试题里经常出现的题型。6.4 时间聚合按年月、周、小时统计时间列处理成datetime类型后分组聚合变得更灵活。热搜词里提到“按时间聚合”这里给出一个通用模板# 先转换时间类型 df[order_date] pd.to_datetime(df[order_date]) # 按年月分组求和 df[year_month] df[order_date].dt.to_period(M) result df.groupby(year_month)[amount].sum() # 使用 resample 按日/周/月重采样 result df.set_index(order_date)[amount].resample(D).sum() result df.set_index(order_date)[amount].resample(W).sum() result df.set_index(order_date)[amount].resample(M).sum()resample适合处理时间序列它要求索引是datetime类型。D表示按天W按周M按月Q按季度。时间聚合在生产环境里常用于日报、周报、月度汇总是数据分析项目里的高频需求。6.5 merge 和 concat多表关联的正确姿势多表关联在真实项目里非常常见。Pandas 的merge和 SQL 的join逻辑非常像df_orders pd.DataFrame({ order_id: [1, 2, 3], user_id: [101, 102, 103], amount: [99, 150, 200] }) df_users pd.DataFrame({ user_id: [101, 102, 104], name: [张三, 李四, 王五] }) # 内连接只保留两边都有的 user_id result pd.merge(df_orders, df_users, onuser_id, howinner) # 左连接保留左表所有订单右表缺失的用 NaN result pd.merge(df_orders, df_users, onuser_id, howleft)how参数的取值含义参数值含义类比 SQLinner取交集INNER JOINleft左表全保留LEFT JOINright右表全保留RIGHT JOINouter并集FULL OUTER JOINconcat则主要用于纵向拼接或横向拼接# 纵向拼接行方向追加 df_all pd.concat([df1, df2], axis0, ignore_indexTrue) # 横向拼接列方向扩展 df_wide pd.concat([df1, df2], axis1)axis0是行方向拼接追加数据axis1是列方向拼接左右合并。初学者经常搞反方向建议记一个口诀axis0上下拼axis1左右拼。7. 数据可视化用 Pandas 自带的绘图接口快速出图7.1 从数据统计到图表输出的最小路径Pandas 本身不是专业可视化库但它内置了基于 Matplotlib 的绘图接口。当你想快速查看数据分布时可以不用写复杂 Matplotlib 代码直接在 DataFrame 上调用.plot()非常节省时间。import pandas as pd import matplotlib.pyplot as plt # 按城市统计总销售额 summary df.groupby(city)[amount].sum().sort_values(ascendingFalse) # 生成柱状图 summary.plot(kindbar, figsize(8, 5)) plt.title(Sales by City) plt.ylabel(Amount) plt.xticks(rotation0) plt.tight_layout() plt.show()kind参数支持多种图表类型bar柱状图、line折线图、pie饼图、hist直方图、box箱线图、scatter散点图。最常见的是bar和line分别对应分类维度和时间趋势。7.2 时间序列折线图和分布直方图时间聚合之后折线图是观察趋势的最佳选择# 按日汇总金额 daily df.set_index(order_date)[amount].resample(D).sum() daily.plot(kindline, figsize(12, 5), titleDaily Amount Trend) plt.show()观察数值分布时直方图更直观df[amount].plot(kindhist, bins20, figsize(8, 5), titleAmount Distribution) plt.show()bins控制直方图分箱数量值越大分箱越细。实际分析中先看直方图有没有长尾、有没有明显偏低或偏高再决定后续业务判断。异常值排查也常常从直方图入手。7.3 中文字体配置的常见问题用 Matplotlib 画图碰到中文乱码是典型问题。macOS 和 Linux 环境默认字体不含中文字符Windows 环境通常好一些。一个常用的临时处理方案是import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei, Arial Unicode MS, sans-serif] plt.rcParams[axes.unicode_minus] False # 解决负号显示异常SimHei是 Windows 常见黑体Arial Unicode MS是 macOS 常见字体。如果本地环境没有对应字体仍然会乱码需要根据操作系统调整字体名称。生产环境生成报表时建议提前确认字体配置避免脚本部署到新机器后图表乱码。8. 常见坑与排查链路从报错日志倒推原因8.1 高频报错KeyError、SettingWithCopyWarning、ValueError实际使用 Pandas 时以下几类报错出现频率极高。报错信息常见原因检查顺序解决建议KeyError: xxx列名不存在或拼写错误先打印df.columns检查列名确认列名是否包含空格或大小写不同SettingWithCopyWarning对 DataFrame 切片尝试赋值时触发的警告检查是否用了链式索引使用df.loc显式操作或先.copy()ValueError: cannot reindex索引不匹配或合并时列重复检查两个 DataFrame 的索引和列合并前检查列名必要时重置索引TypeError对非数值列做数值运算打印df.dtypes先做类型转换日期筛选报错时间列还是字符串类型打印df.dtypes看是否为datetime64先pd.to_datetime转换8.2 排查链路从输入数据到操作逻辑逐步定位遇到任何 Pandas 异常按下面的顺序排查打印df.head()确认数据有没有进来。打印df.columns确认列名与代码里写的一致。打印df.dtypes确认各列类型是否符合预期。检查索引是否重置过是否重复是否需要dropTrue。检查缺失值是否在分组、合并、转数值时引入了 NaN。检查条件表达式布尔索引里的括号是否齐全是否误用and。检查版本差异某些方法在 Pandas 2.x 中用法有调整。这个顺序基本覆盖了 90% 的常见问题。不要一上来就把数据打印几百行先做每一步的小样本验证。8.3 三个与主题强相关的常见坑坑一读入 CSV 后数字列变成object类型。例如金额列含符号或千分位逗号Pandas 无法自动解析为数值于是读成字符串。此时要先清洗文本再转换df[amount] df[amount].str.replace(, , regexFalse) df[amount] df[amount].str.replace(,, , regexFalse) df[amount] pd.to_numeric(df[amount], errorscoerce)坑二groupby之后忘记reset_index()统计结果无法继续当表用。groupby(city)[amount].sum()的结果中city会变成索引。如果你想把结果作为普通 DataFrame 继续参与 merge 或透视需要result df.groupby(city)[amount].sum().reset_index()坑三drop_duplicates没有指定subset去重结果和业务预期不一致。实际项目中完全重复的行很少更多是“某一列或某几列重复但其他列不同”。不指定subset会保留所有列完全一致的第一条但业务想要的可能是按单一业务键去重。一定要明确唯一键。9. 数据分析完整练习从读数据到输出报告的 10 步模板为了让前面内容串成一条线这里给出一套可以直接复用的“数据分析 10 步模板”。它适合常见的数据分析练习项目也适合面试前快速过一遍流程。import pandas as pd import matplotlib.pyplot as plt # 1. 读取数据 df pd.read_csv(sales.csv, encodingutf-8) # 2. 体检数据 print(df.shape) print(df.columns) print(df.dtypes) print(df.head()) # 3. 转换类型 df[order_date] pd.to_datetime(df[order_date], errorscoerce) df[amount] pd.to_numeric(df[amount], errorscoerce) # 4. 处理缺失值 print(df.isnull().sum()) df df.dropna(subset[order_id, amount]) # 5. 去重 df df.drop_duplicates(subset[order_id], keepfirst) # 6. 筛选有效数据 df df[(df[amount] 0) (df[order_date] 2026-01-01)] # 7. 生成辅助列 df[year_month] df[order_date].dt.to_period(M) # 8. 分组聚合 summary df.groupby(city).agg( total_amount(amount, sum), avg_amount(amount, mean), order_cnt(order_id, count) ).reset_index() # 9. 输出结果 print(summary.sort_values(total_amount, ascendingFalse)) summary.to_csv(summary_result.csv, indexFalse, encodingutf-8-sig) # 10. 可视化 summary.plot(kindbar, xcity, ytotal_amount, figsize(8, 5)) plt.title(City Sales Summary) plt.ylabel(total_amount) plt.tight_layout() plt.show()这套模板覆盖了数据读取、类型转换、缺失值、去重、筛选、分组、写出、可视化全流程。实际项目在此基础上增加日志、异常处理、配置外置和结果校验就够了。10. 面试和实战中的高频考察点10.1 数据清洗能力是面试考察重点热搜词里出现“数据分析面试题”“数据分析面经”“微众银行数据分析笔试”等说明求职者普遍关心面试题。Pandas 在面试里很少直接考记忆性 API更多是给一个小数据集让候选人现场完成清洗和统计。常见题型包括给定一个包含缺失值、重复值、日期列、字符串数字混合列的 DataFrame要求清洗后按指定维度汇总。给出两张表让候选人完成关联、分组、透视并输出结果。给定一列时间数据要求按月统计数量或金额。给出一个带有异常值的数据集要求识别并处理。面对这些题最重要的不是记住所有函数而是先想清楚“最终输出是什么”再反推步骤。建议面试前把本文第 4 节到第 6 节的操作各练 3 遍。10.2 知识点速查表操作核心方法易错点读取 CSVpd.read_csv编码、分隔符、日期解析查看信息df.info()先看类型和缺失处理缺失isnull()、dropna()、fillna()填充前想好业务含义去重drop_duplicates明确subset类型转换pd.to_numeric、pd.to_datetime注意errors参数条件筛选df[条件]多条件用加括号分组聚合groupbyagg忘记reset_index多表合并pd.merge列名和how参数透视表pivot_tablefill_value写出文件to_csv、to_excel设置indexFalse快速画图df.plot(kind...)中文字体配置10.3 练习题给你一个包含order_id, user_id, order_date, city, amount, status六列的销售明细表请完成检查每列缺失值数量。按order_id去重。将order_date转为时间类型。筛选出status为success且在 2026 年 1 月之后的数据。按城市和月份统计订单量和总金额。生成城市销售额柱状图。将结果写出为result.csv要求 Excel 打开不乱码。这套练习题就是一个小型数据分析项目能独立完成后Pandas 主流程基本就掌握了。11. 最佳实践学习环境与生产环境需要守住的不同底线11.1 学习阶段可以宽松但要用可复现的方式写代码学习 Pandas 时可以多用 Jupyter Notebook每一步都打印中间结果。但要注意Notebook 里大量“运行某一步后覆盖 df 却又不明白为什么变了”的情况通常是因为变量被反复赋值。建议保持变量名变化次数少关键节点打印 shape 和 head避免前一步的结果悄悄影响后一步。一个好的习惯是df_raw pd.read_csv(sales.csv) df_clean df_raw.dropna(subset[amount]).copy() df_agg df_clean.groupby(city)[amount].sum().reset_index()每一步生成新对象不用反复修改同一个变量这样代码可读性更好排查也更方便。11.2 生产环境需要额外考虑外置配置、日志、异常处理和性能如果只是本地练习直接在代码里写文件路径没有问题。但生产环境的数据清洗脚本需要考虑更多路径不能写在脚本里建议通过配置文件或环境变量传入。文件编码、日期格式、筛选条件等应该允许外部调整。日志输出不能只靠print()。每一步处理完成后至少记录输入行数、输出行数、缺失值数量。这样任务失败时能快速定位是读取阶段、清洗阶段还是聚合阶段出错。异常处理要针对关键步骤。比如读取文件失败、目标列不存在、转换全部变成 NaN这类异常应该直接抛出并中断任务避免带病数据进入下游。import logging logging.basicConfig(levellogging.INFO, format%(asctime)s %(message)s) df_raw pd.read_csv(sales.csv) logging.info(raw shape: %s, df_raw.shape) if amount not in df_raw.columns: raise ValueError(缺少 amount 列) df_clean df_raw.dropna(subset[amount]).copy() logging.info(clean shape: %s, df_clean.shape)性能方面Pandas 处理百万行以内的数据通常表现不错。但如果数据量很大要尽量避免逐行遍历多用向量化操作。apply是循环封装比直接for快但多数情况下仍然不如向量化写法。能用groupby和agg完成的统计不要写for循环。11.3 一套“拿到 DataFrame 后的体检清单”df.shape是否与预期一致。df.columns是否包含目标列是否有空格或不可见字符。df.dtypes是否符合预期金额是否为数值类型日期是否为datetime64。df.isnull().sum()是否有缺失缺失是否集中在关键列。df.duplicated().sum()是否有完全重复行。df.describe()查看数值列的最大值、最小值、均值是否有明显异常值。列名中的空格用df.columns df.columns.str.strip()清理。每次拿到不熟悉的数据集按这个清单走一遍能避免 80% 以上的后续问题。12. 扩展方向从 Pandas 走向数据分析全链路Pandas 是数据分析的基础工具但不是终点。如果要进一步深入建议按以下路径扩展数据量增大后Pandas 单机内存可能不够可以了解 Polars、Dask 或者回到 Spark 生态。Pandas 与 PySpark 都是在处理二维表但一个面向单机内存一个面向分布式集群适用场景不同。热搜词里提到的 Spark 数据分析案例本质上是在更大数据规模下做同样的清洗、聚合和统计。可视化方向Matplotlib 和 Pandas 内置绘图只能满足基础出图。更专业的图表可以用 Plotly、Seaborn 或 pyecharts它们对交互式报表和前端展示支持更好。最后一点建议无论学多少工具数据分析的核心始终是“把原始数据变成可支撑决策的信息”。Pandas 只是帮助你更快完成这个转化。练习时不要只跑通代码而是要盯着输出问一句这组数字在业务上说明什么结果是否符合预期如果不符合是数据问题还是统计口径问题。这样训练出来的能力才会从“会调 API”变成“会做分析”。
返回列表