
做数据分析的人绕不开 Pandas。这不是因为它在所有场景下都是性能最强的工具而是因为它把“处理表格数据”变成了一套可复用、可调试、可交接的代码流程。Excel 打开几万行就开始卡SQL 在复杂清洗面前不够灵活而 Pandas 恰好填上了这个位置既能读入各种格式的数据又能做字段级操作还能和可视化、机器学习无缝衔接。很多初学者的问题不是不想学而是不知道该记哪些 API。市面上的教程通常前几章都在讲 DataFrame 怎么建、怎么改列名最后遇到真实数据时还是无从下手。我的判断是日常数据分析工作里80% 的操作集中在读取、清洗、分组、合并、输出这几类动作上。只要把这条主线练熟Pandas 的入门目标就基本达到了而且完全可以在两个小时左右走完一遍。这篇文章按“速通 实战”的思路组织先讲清楚 Series 和 DataFrame 两个核心概念然后从安装环境开始一步步做数据读取、清洗、分组聚合、多表合并最后用一个完整的订单数据案例把整个流程串起来。读完以后你应该能独立处理一份带缺失值、重复值、日期格式混乱的 Excel 或 CSV 数据并输出可以汇报的分析结果。1. 为什么说 Pandas 值得单独花两小时学1.1 一份常见的脏数据处理起来有多费劲假设你刚接手一份销售订单明细表3 万行数据里面有重复订单、金额为空、日期列在不同月份里格式还不一样。用 Excel 手工处理会是什么感受先筛选空值再挨个判断能不能补接着去掉重复订单然后把日期格式统一这时候你很可能已经花掉了一上午如果下周又来一份结构稍微不同的数据又得重来一遍。用 Pandas 处理过程完全不一样。数据读进来之后缺失值统计是一条命令去重是一条命令日期转换也是一条命令。整个清洗脚本可以保存下来下次数据更新了直接换文件路径重新运行即可。这就是 Pandas 带来的第一步改变把“手工操作”变成“可复用代码”。1.2 为什么是 PandasPandas 是 Python 生态里专门做表格化数据处理的库。它解决的问题非常集中数据读取、数据清洗、数据转换、数据聚合、数据合并、数据输出。如果你准备求职数据分析岗或者日常工作经常要和报表、Excel、SQL 查询结果打交道Pandas 是绕不开的一项基础能力。这里要给出一个明确判断Pandas 不是最快的计算引擎但它是最顺手的“数据加工车间”。它的优势在于灵活。你可以随时对某列做函数变换可以按任意维度的组合分组汇总可以在内存里反复调试每一个中间步骤。这种灵活性和交互性正好弥补了 Excel 和 SQL 之间那块空白地带。1.3 与 Excel、SQL 的定位对比方式优势劣势Excel交互直观小数据量处理方便大数据量卡顿公式难以复用版本管理混乱SQL标准查询和聚合能力强适合生产环境复杂清洗写法繁琐本地数据读取不灵活Pandas灵活可控可编程适合脏数据清洗和中间表加工需要 Python 基础受单机内存限制从实际岗位来看商业数据分析、金融风控数据分析、用户行为分析等方向面试和笔试里大量出现 Pandas 题目考察点通常集中在数据清洗、类型转换、分组聚合和去重逻辑上。这正是本文接下来要覆盖的重点。1.4 两小时的学习节奏我建议你按下面这条路走完先花半小时理解 DataFrame 和索引再用半小时把读写和清洗练熟然后用四十分钟做分组聚合和合并最后留二十分钟跑通一个完整案例。如果基础比较薄弱可以跳过部分扩展内容优先保证主线代码能跑通。2. DataFrame 与 Series先理解数据结构再写代码2.1 用表格思维理解两个核心对象Pandas 里最常见的两个对象是 Series 和 DataFrame。你可以把 Series 理解为“一列带名字的数据”比如某张表里的“销售额”列DataFrame 则是“整个表格”由多个 Series 按列拼接而成。很多初学者一开始就纠结创建 DataFrame 的各种姿势其实没必要。你只需要知道 DataFrame 长什么样、有哪些基本属性等做真实的读写操作时数据自然会被读成 DataFrame。这里更关键的是一个容易混淆的点DataFrame 有行索引也有列名而 Series 只有行索引。2.2 创建一个最小的 DataFrameimport pandas as pd df pd.DataFrame({ 城市: [北京, 上海, 广州], 销售额: [100, 200, 150], 月份: [2025-01, 2025-01, 2025-02] }) print(df) print(形状:, df.shape) print(列名:, df.columns.tolist()) print(数据类型:) print(df.dtypes)输出结果会显示一个三行三列的表格。shape是(3, 3)表示 3 行 3 列columns是列名列表dtypes显示每一列的数据类型。以后拿到任何一份数据第一步都建议先看shape、dtypes和.head()确认数据结构是否符合预期。2.3 索引到底怎么理解索引其实是 DataFrame 中每一行的“名字”默认是 0、1、2 这样的数字。理解索引有两个关键点df[城市]取的是列返回的是 Series。df.loc[0]按行索引取数据df.iloc[0]按位置取第一行。初学者最容易踩的坑是把df[城市]当成取行。记住一个口诀方括号里放字符串取的是列放数字切片取的是行。更规范的写法是取列用df[城市]或df[[城市, 销售额]]取行用df.loc[]或df.iloc[]不要用容易产生歧义的df[0:2]。2.4 快速了解数据的常用方法拿到一个新 DataFrame先用这四个方法建立整体认知df.head() # 查看前 5 行 df.info() # 查看每列非空数量和数据类别 df.describe() # 数值列的基础统计量 df.isnull().sum() # 统计每列缺失值info()在真实项目里非常有用它能帮你一眼看出哪些列有缺失、哪些列被识别成了对象类型。很多时候日期列变成object类型、金额列变成字符串都是因为数据里混入了空值或特殊字符这时info()的结果会在第一步就暴露问题。3. 环境准备Pandas 安装与 PyCharm 配置3.1 Python 版本与 Pandas 版本适配开始安装前先确认你本机的 Python 环境。一个很常见的问题是Python 3.10 到底应该装哪个版本的 Pandas最稳妥的方法不是背版本号而是让包管理器自动解析依赖。打开终端或命令行执行python --version确认 Python 版本后直接使用 pip 安装pip install pandas如果你的 Python 是 3.10 及以上那么优先安装 Pandas 最新稳定版即可。如果安装后出现ImportError或编译报错再根据错误提示检查版本兼容性。更谨慎的做法是安装时查看 Pandas 发布说明中关于 Python 版本的声明避免盲目装太旧的版本。3.2 用 pip 安装 Pandas如果直接安装速度慢可以指定国内镜像源pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple建议同时安装openpyxl和pyarrow这两个包分别用于 Excel 读写和 Parquet/Feather 高性能格式读写pip install pandas openpyxl pyarrow -i https://pypi.tuna.tsinghua.edu.cn/simple安装成功后打开 Python 交互环境或创建脚本验证import pandas as pd print(pd.__version__)只要不报错说明 Pandas 已经可以正常使用。3.3 在 PyCharm 里安装 Pandas如果你习惯用 PyCharm可以通过图形界面安装不需要单独记命令。操作路径是File-Settings-Project: 你的项目名-Python Interpreter点击界面右侧的 “” 号在搜索框中输入pandas然后点击左下角的Install Package。安装完成后同一个解释器下执行import pandas as pd即可。这里有一个常见的坑如果你在终端里用pip install pandas安装但 PyCharm 里选的解释器是另一个 Python 环境那就会提示找不到 pandas。遇到这种情况确认 PyCharm 的 Python Interpreter 路径和你执行 pip 的 Python 是否一致即可。4. 数据读取与写出从 CSV、Excel 到 Parquet、Feather4.1 CSV 和 Excel 是最常见的输入格式日常工作中CSV 和 Excel 是使用频率最高的两种数据格式。Pandas 读取它们只需要一行代码import pandas as pd # 读取 CSV注意中文编码 df_csv pd.read_csv(订单数据.csv, encodingutf-8-sig) # 读取 Excel 指定 Sheet并解析日期列 df_excel pd.read_excel(订单数据.xlsx, sheet_name明细, parse_dates[下单日期])读取 CSV 时最容易踩的坑是中文乱码。如果文件里包含中文可以尝试encodingutf-8-sig或encodinggbk。utf-8-sig还有一个好处它能把带 BOM 的 UTF-8 文件正确识别后续写出的 CSV 用 Excel 打开也不会乱码。parse_dates参数可以直接把指定列解析为日期类型省得后面再做一次转换。如果日期格式比较特别比如2025/1/1 10:30也可以用pd.to_datetime()做更灵活的转换。4.2 写出结果文件处理完成后可以按需保存为 CSV 或 Excel# 保存为 CSV不保存索引列 df_csv.to_csv(清洗后订单.csv, indexFalse, encodingutf-8-sig) # 保存为 Excel df_excel.to_excel(清洗后订单.xlsx, sheet_name结果, indexFalse)这里需要特别强调indexFalse如果不加Pandas 会把行索引当作一列写入文件最终文件里会多出一列没有意义的数字这在向业务方交付数据时非常容易引发疑问。4.3 高性能格式Parquet 和 Feather如果你处理的数据量比较大或者一份 DataFrame 需要反复读取建议考虑 Parquet 或 Feather 格式。两者都是列式存储格式读写速度远快于 CSV而且能保留数据类型信息不需要在读取后再手动转类型。# 写入 Parquet df.to_parquet(订单数据.parquet, enginepyarrow) # 写入 Feather df.to_feather(订单数据.feather) # 读取 df_parquet pd.read_parquet(订单数据.parquet) df_feather pd.read_feather(订单数据.feather)在单机 Python 环境里Pandas 配合 PyArrow 读写这些列式格式已经能模拟出不少 Spark 场景下的存储优化思路。理解了列式存储后面再接触 Spark、ClickHouse 这类对列式存储有深度依赖的引擎时会容易很多。格式适用范围特点CSV通用交换、交接给业务可读性好文件大读取慢Excel给非技术同事看交互方便大数据量不适用Parquet大数据量、列式分析压缩率高保留类型读取快Feather同进程反复读写读写极快适合中间结果5. 数据清洗缺失值、重复值、数据类型转换5.1 缺失值处理真实数据几乎没有完全没有缺失值的。拿到数据后先统计缺失情况print(df.isnull().sum())处理缺失值通常有两种思路删除或填充。删除如果缺失行占比很小直接删除如果某列缺失太多可以整列删除。填充数值列用均值或中位数填充分类列用众数时间序列用前向填充。# 删除 amount 列为空的行 df df.dropna(subset[amount]) # 用中位数填充数值列 df[amount] df[amount].fillna(df[amount].median()) # 用众数填充分类列 df[city] df[city].fillna(df[city].mode()[0])这里要注意dropna()和fillna()都不会原地修改原 DataFrame除非传入inplaceTrue但实际工程中更推荐用df df.dropna(...)这种重新赋值方式逻辑更清晰也避免链式修改带来的副作用。5.2 去重指定两列相同就取第一条重复数据分析里很常见比如同一笔订单在明细表里被导出了多次。去重最核心的参数是subset它决定“哪些列相同算作重复”。举个例子如果希望订单号相同且用户 ID 也相同的数据视为重复保留第一条# 当 order_id 和 user_id 两列都相同时保留第一次出现的行 df df.drop_duplicates(subset[order_id, user_id], keepfirst) print(df.shape)keepfirst表示保留第一次出现的行这也是默认行为正好对应“两列值均相同则取第一条”的需求。如果希望保留最后一条改成keeplast即可。5.3 数据类型转换数据清洗中类型转换是绕不开的一步。常见情况有三种金额列被读成了字符串需要转数值。日期列是字符串需要转日期类型。分类字段被读成了字符串可以转category减少内存。# 字符串转数值无法转换的变成 NaN df[amount] pd.to_numeric(df[amount], errorscoerce) # 字符串转日期 df[order_date] pd.to_datetime(df[order_date], errorscoerce) # 分类字段转 category 类型 df[city] df[city].astype(category) print(df.dtypes)errorscoerce是很实用的小技巧当某些奇怪字符串无法转换时不会直接报错中断而是变成缺失值。转换完成后再用缺失值处理逻辑去排查脏数据整个流程就顺畅多了。5.4 清洗步骤的固定套路结合经验我给出一套通用的清洗顺序info()查看整体结构和缺失。isnull().sum()统计缺失量决定删除还是填充。drop_duplicates()去重。pd.to_datetime()、pd.to_numeric()做类型转换。describe()看数值列的分布是否合理。按照这个顺序处理数据基本能覆盖绝大多数脏数据场景。如果后面发现分析结果异常再回头检查是否有异常值或过滤条件遗漏。6. 分组聚合与多表合并6.1 groupby 到底在做什么分组聚合是数据分析中最重要的操作之一Pandas 的groupby底层逻辑可以总结为三步拆分、应用、合并。先按某个字段把数据分成若干组然后对每一组执行聚合计算最后把结果拼回一张表。看一个最简单的例子# 按城市分组求销售额总和 city_amount df.groupby(city)[amount].sum() # 按城市和品类分组同时算多个统计量 result df.groupby([city, category])[amount].agg([sum, mean, count]) print(result)groupby(city)[amount].sum()的含义是按城市分组对每组里的amount列求和。很多初学者容易写错的地方是忘记加[amount]导致对整张表的所有数值列都做了聚合结果列会变多不够干净。如果需要多样化的统计量用agg()传入列表或字典result df.groupby(city)[amount].agg([sum, mean, max, min]) result.columns [总销售额, 平均销售额, 最大金额, 最小金额]6.2 分组后如何转回普通表groupby的结果仍然是 DataFrame 或 Series但分组字段通常会成为索引。如果你想把这个结果保存成 CSV 或者继续和其他表做合并通常需要把索引恢复成普通列result result.reset_index()这是新手非常容易漏掉的一步。如果不做reset_index()保存到 CSV 时分组字段会变成第一列却没有列名后续别人接手数据时容易误解列结构。6.3 concat 与 merge两种合并方式数据合并有两个常用函数concat和merge。concat适合简单的数据拼接比如纵向追加多张结构相同的月度表或者横向拼接两个字段不同的表# 纵向拼接两张表 df_all pd.concat([df_jan, df_feb], axis0, ignore_indexTrue) # 横向拼接两张表 df_wide pd.concat([df_info, df_amount], axis1)merge则更像 SQL 里的 JOIN通过一个或多个键把两张表关联起来user_info pd.DataFrame({ user_id: [1001, 1002, 1003], user_level: [普通, VIP, 普通], register_date: [2024-01-01, 2024-06-01, 2023-11-11] }) df_merged pd.merge(df, user_info, onuser_id, howleft) print(df_merged.head())how参数决定保留哪边inner是交集left保留左边全部right保留右边全部outer是并集。实际业务里最常用的是left因为往往是以订单表为主表去补充分用户信息订单不能少。7. 完整实战订单数据分析7.1 构造一份模拟订单数据为了演示完整流程我们先用代码生成 1000 行模拟订单数据并故意做脏日期列先变成字符串、部分金额缺失、部分行重复。import pandas as pd import numpy as np rng np.random.default_rng(42) order_id [fORD{i:05d} for i in range(1000)] user_id rng.integers(1000, 5000, 1000) order_date pd.date_range(2025-01-01, periods1000, freqD).astype(str) cities rng.choice([北京, 上海, 广州, 深圳, 杭州], 1000, p[0.3, 0.25, 0.2, 0.15, 0.1]) categories rng.choice([手机数码, 服饰鞋包, 食品生鲜, 家居日用], 1000, p[0.4, 0.3, 0.2, 0.1]) amounts np.abs(rng.normal(500, 200, 1000)).round(2) status rng.choice([已完成, 退款, 待发货], 1000, p[0.8, 0.1, 0.1]) df pd.DataFrame({ order_id: order_id, user_id: user_id, order_date: order_date, city: cities, category: categories, amount: amounts, status: status }) # 人为制造脏数据重复行和缺失值 df pd.concat([df, df.iloc[[0, 1]]], ignore_indexTrue) df.loc[50, amount] np.nan df.loc[120, city] None print(df.shape) print(df.isnull().sum())7.2 从清洗到分析接下来按照清洗流程处理# 1. 去重订单号和用户ID同时相同视为重复 df df.drop_duplicates(subset[order_id, user_id], keepfirst) # 2. 删除 amount 缺失的样本 df df.dropna(subset[amount]) # 3. 日期转 datetime 类型 df[order_date] pd.to_datetime(df[order_date]) # 4. 金额统一转 float df[amount] pd.to_numeric(df[amount], errorscoerce) # 5. 再删一次转换后可能产生的缺失值 df df.dropna(subset[amount]) print(df.shape) print(df.dtypes)清洗完成后分别做几类分析。按城市汇总销售额city_summary df.groupby(city)[amount].sum().sort_values(ascendingFalse).reset_index() print(city_summary)按月统计销售额趋势df[month] df[order_date].dt.to_period(M) monthly_trend df.groupby(month)[amount].sum().reset_index() print(monthly_trend)统计品类销售笔数和金额category_summary df.groupby(category)[amount].agg([count, sum]).reset_index() category_summary.columns [品类, 订单数, 销售额] category_summary category_summary.sort_values(销售额, ascendingFalse) print(category_summary)7.3 保存分析结果city_summary.to_csv(城市销售额.csv, indexFalse, encodingutf-8-sig) monthly_trend.to_csv(月度趋势.csv, indexFalse, encodingutf-8-sig) category_summary.to_csv(品类汇总.csv, indexFalse, encodingutf-8-sig)7.4 如何判断案例是否成功运行后你应该能看到清洗前约 1002 行清洗后约 1000 行且每列的非空数量一致。city_summary按城市统计出 5 行销售总额顺序按销售额从高到低排列。monthly_trend按月份展示销售额变化日期已经是时间类型。category_summary有 4 行数据包含订单数和销售额两列。如果某个环节结果和预期差很多先从df.shape和df.isnull().sum()回看清洗是否生效。最常见的问题就是日期列没有成功转成datetime导致.dt.to_period(M)报错。这套流程同样适用于门店销售、足球比赛数据、金融风控评分等场景。思路是一致的先清洗再按维度分组统计最后输出给业务或模型使用。8. 常见问题与排查思路问题现象可能原因排查方式解决方案ModuleNotFoundError: No module named pandas包未安装或解释器不一致确认 PyCharm 的 Python Interpreter 和执行命令的 Python 是否同一个在对应解释器里安装 pandas读 CSV 中文乱码编码不匹配用文本编辑器查看文件编码尝试encodingutf-8-sig或encodinggbk日期列是对象无法用.dt日期未解析打印dtypes确认列类型用pd.to_datetime转换出现SettingWithCopyWarning对 DataFrame 切片后再赋值检查代码链式赋值的位置切片后用.copy()创建副本或改用loc大文件读取内存不足数据量超过内存查看文件大小和实际所需字段只读必要列用chunksize分批读取drop_duplicates去重后行数没变化重复行在所有列上并不完全相同查看指定列的重复值检查subset参数是否覆盖所需列保存 Excel 报错缺少openpyxl查看错误日志pip install openpyxl9. 最佳实践与后续学习建议9.1 写分析代码的工程习惯写 Pandas 代码时建议养成几个习惯。第一不要在原 DataFrame 上反复修改除非你能完全控制流程。更稳妥的做法是保留原始数据清洗后的结果另存为新变量避免后面调试时把原始数据也污染了。第二优先用向量化操作代替循环。Pandas 的底层大量使用 NumPy 数组运算一次对整列做加减比for循环逐行处理快一个量级。如果确实需要复杂逻辑优先考虑apply()或map()而不是for i in range(len(df))。第三文件保存时统一加indexFalse和合适的编码。中文环境建议encodingutf-8-sig这样交接给 Excel 用户时不会乱码。9.2 大数据量下的实践建议Pandas 适合单机内存能放下的数据。如果数据量大到读入时内存吃紧可以这样优化读取时指定usecols只读需要的列。对枚举值有限的分类列使用category类型。使用chunksize分批读取大文件逐块处理后合并结果。需要反复使用的中间结果优先保存成 Parquet 或 Feather。9.3 后续学习方向Pandas 学完之后下一步通常有两类方向。一类是补齐数据分析和可视化的闭环比如学习 NumPy 的数组计算原理、Matplotlib 和 Seaborn 的画图方法让分析结果能直接形成图表。另一类是往数据工程和机器学习方向走学习 SQL、数据仓库、特征工程再到 Scikit-learn 做建模实践。无论你后续是否借助 AI 工具辅助生成 Pandas 代码建议都保持一个底线能看懂每一步在做什么能跑通验证流程能面向业务结果做解释。工具可以辅助写代码但对数据的判断力还是来自你亲手处理过足够多脏数据之后的积累。现在你可以打开 PyCharm照着第 3 章的安装步骤把环境搭好再跑一遍第 7 章的案例。跑通之后把数据源换成你自己手上那份 Excel 或 CSV用同样的清洗和分析流程完成一次完整的处理。这个过程走完Pandas 的主干能力就已经在你的日常工具箱里了。