简介这是一本面向已具备Python基础读者的Pandas实战指南通过近百个真实案例系统讲解数据清洗、分组聚合、时间序列分析以及与Matplotlib和Seaborn集成可视化等核心技能。资源为1个PDF电子书压缩包大小53.38MB文件类型单一便于阅读与检索。目前已有270人学习适合需要系统提升数据处理能力的数据分析初学者与从业者。书中案例源自真实项目不仅覆盖布尔索引、多重索引、SQL式数据合并等高级操作还专门阐述时间序列功能的独特应用每个案例均配有详细解决方案并在交互式编程笔记本中演示读者可借此快速掌握隔离数据子集、分组聚合、重构整理数据、为机器学习准备数据集等实战方法。通过学习读者能高效完成从数据清洗到可视化呈现的完整流程并将Pandas直接对接可视化库生成富有洞察力的图表显著提升日常数据分析效率。1. Pandas数据分析实战为什么你学了函数却做不出一个完整分析很多人在 Pandas 上的真实状态是单看每个函数都懂df.groupby、pd.merge、fillna背得滚瓜烂熟但一接到真实的 CSV 或 Excel 数据就卡住——要么不知道先处理哪一步要么跑出来的结果跟业务对不上。这份资源不是函数字典而是把 Pandas 放进完整的数据分析流程里从读取 messy 数据、清洗、类型转换、分组聚合到导出结果每一步都有可跑的代码和能落地的参数。它适合刚学完 Pandas 基础但没做过完整项目的初学者也适合用 Excel 做分析、想转向 Python 流程的职场人。核心思路是先明确每个阶段要解决什么问题再调对应的 API而不是对着函数列表一个个试。实战里真正花时间的从来不是语法是数据和预期对不齐时的排查能力。2. 环境与数据准备先把 DataFrame 的底子打对2.1 安装与版本选择pandas 不是装上了就能用用 pip 安装 pandas 是最常见的方式但很多人第一次装完就翻车——ImportError: No module named pandas或者装的是 Python 2 的包。这里有一个最简单也最容易被忽略的点先确认当前环境的 Python 版本和 pip 指向。# 先确认解释器位置和版本再决定装哪个包 import sys print(sys.executable) # 看看当前 Python 解释器的绝对路径 print(sys.version) # 确认是 3.8pandas 2.x 要求 Python 3.8 # 安装 pandas在终端执行不是在脚本里 # pip install pandas很多人踩过这样一个坑在 Jupyter Notebook 里!pip install pandas装成功了但新建的 .py 文件用命令行跑时又报 ModuleNotFoundError。原因是 pip 对应的解释器和运行脚本的解释器不是同一个。我一般会先用sys.executable确认路径再用这个路径下的-m pip去安装。比较稳妥的做法是# 直接用 python -m pip 安装保证装到当前解释器 python -m pip install pandas numpy openpyxl这里openpyxl是必须的——pandas 读写 .xlsx 文件依赖它只装 pandas 读 Excel 会报ImportError: Missing optional dependency openpyxl。numpy 是 pandas 的底层依赖装 pandas 时会自动带上但显式指定版本更可控。装完验证一下版本import pandas as pd print(pd.__version__) # 期望 1.5.x 或 2.xpd.__version__这个属性很多人不知道。如果输出 2.x注意append方法已经被移除了网上老教程里的df.append()在 2.x 里跑不通要改用pd.concat。2.2 从 CSV 和 Excel 读取数据参数别用默认值读取是实战里第一个分水岭。用默认参数读 CSV 经常得到一列乱码或者数字列变成字符串。读文件的正确姿势是先想清楚文件长什么样再决定参数import pandas as pd # 读取 CSV处理编码、分隔符、空值标记 df_csv pd.read_csv( sales_data.csv, encodingutf-8, # 乱码时试试 utf-8-sig 或 gbk sep,, # 分隔符tab 分隔用 \t na_values[NULL, N/A, ?], # 把多种缺失标记统一成 NaN parse_dates[order_date], # 直接解析日期列 dtype{user_id: str} # 用户 ID 按字符串读避免精度丢失 ) print(df_csv.shape) print(df_csv.dtypes)逻辑说明encodingutf-8适合大部分数据源但国内导出的 CSV 经常是 GBK 编码读出来乱码时改成gbkna_values很实用——业务系统导出的文件里缺失值可能是字符串NULL或N/A不指定的话这些值不会被当成 NaN后续统计会出错。parse_dates让日期列直接变成datetime64类型省掉后面手动的pd.to_datetime。dtype参数解决的是用户 ID、手机号这类长数字列——不指定的话会被读成 int64超过 15 位就丢失精度这是 Excel 导出数据中非常高发的暗坑。读 Excel 的差异主要在 sheet 名和表头# 读取 Excel指定 sheet 和表头位置 df_excel pd.read_excel( sales_data.xlsx, sheet_name订单明细, # 默认读第一个 sheet按名称指定更可靠 header0, # 表头在第 0 行 skiprows1 # 如果第 0 行是标题说明就跳过去 )header0是默认行为但实际文件里表头经常不在第一行上面有一行报表标题或导出说明。这时候如果不设skiprows读进来的第一列 data 里会混进标题文本pandas 会把字段名弄脏。我遇到这类文件时会先pd.read_excel(file, nrows5)看前几行长什么样再决定 skip 几行。这一步花 30 秒能省下后面解包数据的大把时间。2.3 数据结构创建从字典和列表构造 DataFrame 的两种写法实战中数据不总是来自文件经常需要手写测试数据或从接口返回的 JSON 构造 DataFrame。两种最常用的构造方式各有用武之地# 方式一用字典构造key 是列名value 是整列数据 import pandas as pd data_dict { city: [北京, 上海, 广州, 深圳], sales: [120, 260, 180, 210], growth: [0.15, 0.32, -0.05, 0.18] } df1 pd.DataFrame(data_dict) print(df1) # 方式二用列表嵌套构造每行一个元组/列表指定列名 rows_data [ (北京, 120, 0.15), (上海, 260, 0.32), (广州, 180, -0.05), ] df2 pd.DataFrame(rows_data, columns[city, sales, growth])第一种写法符合人对表格的直觉——按列组织数据适合做测试数据第二种更像从数据库查出来的原始行适合处理接口返回的 JSON 数组。后面的分析操作对两种方式构造的结果没有区别但分享一个偏好凡是列很多超过 20 列的场景用字典构造可读性高得多因为列名一目了然。3. 数据清洗与类型转换数据分析里八成的时间花在这3.1 缺失值与重复值先摸清分布再动手删拿到数据集先别急着分析第一步永远是看缺失和重复的分布。很多人上来就dropna()一把梭结果把有业务含义的空值也删了——比如用户没填手机号这个 NaN 本身是一条有效信息。正确的姿势是先量化# 缺失值分布看每列缺多少、占多少比例 missing_stats df.isna().sum() missing_ratio missing_stats / len(df) # 把两列拼一起看 missing_summary pd.DataFrame({ 缺失数量: missing_stats, 缺失比例: missing_ratio }) print(missing_summary[missing_summary[缺失数量] 0])df.isna()返回每个单元格是否是缺失值的布尔矩阵sum()按列求和就能得到每列缺失个数。这里注意isna()和isnull()完全等价但没有isnan()——那是 numpy 的函数用在不该用的地方会报错。缺失比例超过 30% 的列如果它不是关键指标直接删除是合理的低于 5% 的列可以用行删除或填充处理。重复值处理有一个容易被忽略的细节重复有「完全重复」和「关键列重复」两种。完全重复直接删关键列重复需要业务判断保留哪一行# 查看完全重复的行 print(df.duplicated().sum()) # 删除完全重复 df_clean df.drop_duplicates() # 按关键列去重同一订单号保留第一条 df_dedup df.drop_duplicates(subset[order_id], keepfirst)subset参数指定判断重复的列集合keepfirst保留第一次出现的行keeplast保留最后一次。实战里一个血泪经验去重前先确认字段的语义。比如订单表里order_id本来就有唯一约束但同一个订单拆成多个包裹发货时order_id会重复——如果你按order_id去重就把真实数据删坏了。所以去重前至少看一眼重复行的原始数据dup_mask df.duplicated(subset[order_id], keepFalse) print(df[dup_mask].head(10))把keepFalse时所有重复行不是去重后的保留行都打印出来看再做决定。3.2 数据类型转换object 列全是坑df.dtypes看一下很多从 CSV 读进来的列显示object这在 pandas 里就是「字符串或者乱七八糟的混合类型」。业绩表里金额是字符串是很常见的排序、求和都会出错——字符串排序是按字典序「10」会排在「9」前面。类型转换的目标是把每列推到正确的 dtype# 转换数值列errorscoerce 把无法转换的值变成 NaN df[sales] pd.to_numeric(df[sales], errorscoerce) # 转换日期列统一格式暴力解析 df[order_date] pd.to_datetime( df[order_date], format%Y-%m-%d, # 显式指定格式解析更快更稳 errorscoerce # 不合法日期变成 NaT ) # 转换分类列占内存小groupby 更快 df[channel] df[channel].astype(category)参数说明errorscoerce是三个选项里最常用的——非法值置为 NaN而不是报错errorsraise默认或保留原值errorsignore。用errorsraise遇到脏数据整个脚本崩掉用coerce至少能跑完然后你通过isna()检查哪些值没转成功。pd.to_datetime的format参数建议显式写不写的话 pandas 会尝试多种解析格式速度慢且可能出现歧义解析——比如2024/03/01和03/01/2024在不指定格式时可能被当成不同含义。3.3 条件筛选与替换别用循环用向量化新手拿到需求「把销售额大于一万的标记为高价值」会写 for 循环这是性能最差的做法。pandas 的底层是 numpy 向量化整列操作比逐行循环快两个数量级# 条件筛选多条件用 |注意每个条件要加括号 high_value df[ (df[sales] 10000) (df[channel] 线上) ] # 条件赋值新增列用 np.where 实现 if-else import numpy as np df[tier] np.where(df[sales] 10000, 高价值, 普通) # 复杂多分支用 np.select conditions [ (df[sales] 50000), (df[sales] 10000), (df[sales] 0) ] choices [S级, A级, B级] df[level] np.select(conditions, choices, default其他)np.where(条件, 真值, 假值)是最简单的 if-else 向量化np.select处理多分支比一堆loc嵌套清晰得多。这里一个常见误用和|不能写成and和or——and是 Python 关键字用在 numpy 数组上会报ValueError: The truth value of an array is ambiguous。这个报错非常经典搜索引擎一搜一大片。另外注意多条件时每个条件要用括号包起来不然的优先级会和比较运算符打架结果完全不对。4. 分组聚合与业务分析从明细表到结论4.1 groupby 的核心逻辑拆分-应用-合并groupby 是 pandas 里面函数最多、最容易绕晕的部分。它的运作分三步按分组键把数据拆开对各组执行聚合函数把结果合并回一张表。理解了这三步你才能判断结果为什么和自己手算的对不上# 单列分组 多列聚合 summary df.groupby(channel).agg( 总销售额(sales, sum), 订单数(order_id, count), 平均客单价(sales, mean) ) print(summary)groupby(channel)指定分组键.agg()里我用的是「新列名(原列名, 聚合函数)」这种写法——这是 pandas 0.25 之后引入的 NamedAgg 模式比原来{sales: sum}的字典形式好在输出列名可控、语义清晰。(sales, sum)表示对 sales 列求和。注意如果传的是(order_id, count)count会统计非空值数量——因为 order_id 理论上不会有缺失所以count和size结果相同但如果有缺失值你就不该用count而用size()size 是不忽略 NaN 的行数统计。多级分组再加排序能直接产出业务要看的 Top 排名# 多列分组按渠道城市分组看销售额和环比 summary2 df.groupby([channel, city]).agg( 销售额(sales, sum), 门店数(store_id, nunique) ).reset_index() # 按销售额降序排取每个渠道 Top 3 summary2 summary2.sort_values([channel, 销售额], ascending[True, False]) top3 summary2.groupby(channel).head(3)分组后做.head(3)返回每组的前 N 行这是分组 Top N 的经典写法。nunique统计的是去重后的数量用来算门店数、用户数这类指标非常合适——如果你用count算门店数同一个门店出现多次会被重复计算结果直接错掉。4.2 合并与连接merge 的四种连接方式多张表合并是真实业务里跑不掉的环节。订单表关联用户表、商品表关联类目表——pandas 的merge和 SQL 的 JOIN 语义一致但很多初学者在这里翻车两个表里都有id列没指定on或suffixesmerge 完发现多出来一堆_x和_y# 订单表关联用户表left 是订单表right 是用户表 orders pd.read_csv(orders.csv) users pd.read_csv(users.csv) merged pd.merge( leftorders, rightusers, onuser_id, # 关联键 howleft, # 左连接保留全部订单 suffixes(_订单, _用户) # 重复列名的后缀避免 _x/_y ) print(merged.shape)连接方式的选择howleft以左表为基准右表匹配不到的填 NaNhowinner只保留两边都匹配上的行——做关联时如果你不确定主表是谁先分别看两个表的shape确认行数再下手。关联后立即验证merged[订单金额].isna().sum()如果出现大量缺失说明连接键在两表之间不匹配常见原因是类型不一致——订单表的user_id是字符串用户表的user_id是 int64要先用astype统一。4.3 透视表与交叉分析pivot_table 一步到位Excel 里的数据透视表功能pandas 对应的是pivot_table。它可以同时完成分组、聚合、汇总省去多次 groupbypivot pd.pivot_table( df, valuessales, # 要聚合的列 indexcity, # 行分组键 columnschannel, # 列分组键 aggfuncsum, # 聚合函数 marginsTrue, # 显示总计行/列 fill_value0 # 空值填 0 ) print(pivot)index对应透视表的行字段columns对应列字段aggfunc支持传入列表比如aggfunc[sum, mean]一次算求和和均值。marginsTrue会生成「总计」行和列——这在核对数据时非常有用如果行方向总计和原表df[sales].sum()对不上说明有分组键为空的数据被排除了。fill_value0把 NaN 填 0 只是展示层面的处理不改原数据。5. 实战排查pandas 高频报错与数据对不上的五个坑5.1 报错SettingWithCopyWarning改了副本原表纹丝不动现象执行df_slice[new_col] 1后控制台飘出一条黄色警告原表 df 里没有新增列或者新增了但值全是 NaN。原因df_slice df[df[列] 0]创建的是一个视图view不是副本。pandas 无法确定你是想改视图还是改原表于是警告你操作可能没生效。实际上有时候改了副本原表变了有时候没变——行为不确定这就是玄学。解决对切片明确复制一份再操作。df_slice df[df[sales] 100].copy() # 显式 .copy() df_slice[new_col] 1从那以后我凡是df后面带筛选条件的行一律先.copy()宁多一步不赌。这个习惯能消掉 90% 的诡异修改无效问题。5.2 报错ValueError: The truth value of a DataFrame is ambiguous现象if df[sales] 100:然后整个脚本崩掉。原因df[sales] 100返回的是一个布尔 Series不是一个 True/False。Python 的if需要单个布尔值无法决定这个 Series 的「真值」是什么——是全部满足才算真还是任一满足pandas 拒绝猜。解决用.any()或.all()显式说明意图if (df[sales] 100).any(): # 只要有一个满足就进分支 print(存在高销售额记录)注意条件筛选时写df[(df[sales] 100)]是没问题的因为方括号里接受布尔 Series问题只出在if/while语句里。这两类场景别混。5.3 合并后行数暴增一对多没控制住现象pd.merge之后新表的行数比左表多了好几倍明显不合理。原因右表的关联键有重复。比如订单表按user_id关联用户表如果用户表里同一个user_id有两行比如历史记录没清理左表的每一单都会匹配两次行数翻倍。这是 merge 里最容易踩的坑但也是最好排查的。解决merge 前先查重复键。# 查右表关联键的重复情况 dup_count users[user_id].duplicated().sum() print(fusers 表 user_id 重复 {dup_count} 行)users[user_id].duplicated().sum()一行就能确认。如果确实要保留重复行就明确连接意图如果重复是脏数据先去重再 merge。我自己的固定流程是merge 前必查两表关联键的duplicated().sum()等于 0 才继续。5.4 日期列排序错乱object 类型当时间排序现象按日期排序后的数据看起来没有顺序2024-01-05 排在 2024-01-01 前面。原因日期列是字符串类型排序按字典序进行。「2024-01-05」这类格式碰巧字典序和年月日一致但如果数据是「2024/1/5」或者「2024-1-05」字符排序就全乱了。解决先转 datetime 再排序。df[order_date] pd.to_datetime(df[order_date]) df df.sort_values(order_date)排完序后验证一下df[order_date].is_monotonic_increasing返回 True 才说明排序生效。如果日期是月末数据转 datetime 后sort_values的时间复杂度是 O(n log n)大数据量下没有性能问题。还有一个细节pd.to_datetime转换后如果有无效日期比如 2月30日会生成NaT这些行排序时会被放到最后——用dropna(subset[order_date])清掉再排。5.5 聚合结果和 Excel 核对不上count 与 size 的天壤之别现象用groupby算某渠道订单数比 Excel 透视表少了几条找半天找不到原因。原因.agg(count)统计的是该列非空值的数量如果这一列里有 3 个空值count就少算 3。而 Excel 透视表默认是数行数。两个口径不一样结果自然对不上。解决明确你要的口径——数行数用size()数非空字段用count。# size() 数的是行数包含空值行 订单数 df.groupby(channel).size() # count 是某列的非空值数 订单数2 df.groupby(channel)[order_id].count()这两个结果在数据不干净时不一样。和业务对口径时优先用size()因为它最接近「订单表里有多少行」的直观理解。如果是和别人对接把口径写进交付文档里省得月底对不齐互相甩锅。6. 用 .pipe() 把清洗流程串成流水线让脚本不再一团乱麻前面所有步骤都是散装的但实战里数据清洗少则五步多则十几步——如果每次跑都在 Notebook 里从上到下重来改一个中间步骤就要重新执行后面所有代码而且中间变量遍地都是。.pipe()方法的思路是把每一步封装成「输入一个 DataFrame、输出一个 DataFrame」的函数再用.pipe()串联起来让整个流程可读、可复用、可修改。def clean_dates(df): 统一日期列格式非法值标出但保留留痕 df[order_date] pd.to_datetime(df[order_date], errorscoerce) df[_date_invalid] df[order_date].isna() return df def fill_channel(df): 渠道空值填 unknown不做删除 df[channel] df[channel].fillna(unknown) return df def add_tier(df): 新增客户分层列 df[tier] np.where(df[sales] 10000, 高价值, 普通) return df # 用 pipe 串联参数 dx 是其他附加参数 df_processed ( df_raw .pipe(clean_dates) .pipe(fill_channel) .pipe(add_tier) .pipe(lambda d: d.drop_duplicates(subset[order_id], keeplast)) ) print(df_processed.info()).pipe()的妙处在于每一步之间数据流是显式的——上一个函数的返回值直接成为下一个函数的输入不再依赖脚本执行顺序也不存在「上一步跑没跑」的疑虑。函数内部不需要抛出一个新变量直接改传入的 df 再返回即可这也意味着如果你想换处理顺序只需调整.pipe的行序逻辑零改动。如果某个函数还有额外参数写成.pipe(func, 参数值)就行不用lambda包一层——这个特性在参数很多时特别好用。在执行.pipe之前我每次都会做一次快照import pickle # 存原始数据的副本处理完还能回头比差异 with open(raw_data_snapshot.pkl, wb) as f: pickle.dump(df_raw, f)这个习惯帮过我太多次——处理到一半发现思路错了或者想对比清洗前后的统计差异直接读快照重来不用重新去导文件。pipeline 跑完后的验证也有固定套路对比df_raw.shape和df_processed.shape行数变化说明了清洗的激进程度再把df_processed[channel].value_counts()和 Excel 透视表、BI 报表核对一遍数字对得上才敢交付。从那以后我每次做 Pandas 分析都强制自己把清洗逻辑全部挪进.pipe()函数散装处理代码一律不下放。这个迁移过程会逼你把每个步骤的输入输出想清楚分析质量反而上了一个台阶。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
LSTM多变量成绩预测的Python实战:从数据到模型 简介:这套LSTM系列教程资源面向Python机器学习初学者与时间序列预测实践者,聚焦多变量预测、单变量预测及多步预测等典型任务,覆盖股票、天气、销售等常见应用场景,帮助用户从数据预处理到模型评估建立完整预测流程。资源共33个文… · 2026/9/25 23:21:19
Java多人聊天系统实战:从Socket到线程池的完整构建指南 简介:一套用于 Java 课程设计与期末项目的简易多人聊天系统实现,主要面向有 Java 基础、正在学习网络编程或 Socket 通信的在校学生。系统面向校园师生沟通场景,覆盖用户注册登录、聊天室的创建与加入、文本消息的实时收发等核心流程… · 2026/9/25 23:21:12
河北核雕手串纯手工靠谱商家推荐:金丝楠木手串100真品官方旗舰店客户口碑力荐 文章开篇以行业痛点从用户角度出发,列举本行业大众选择时最常见的4大踩坑难题、选购顾虑、普遍痛点,使用用户高频搜索口语,不植入品牌。 玩橄榄核手串的时候,你有没有遇到过这些糟心事?挑的时候满心欢喜,拿到手才发现… · 2026/9/25 23:21:12
Cisco Packet Tracer 5.3:下载、安装、汉化、排错与实验完全指南 前几天连续收到三条私信,都在问同一个问题:Cisco Packet Tracer 5.3到底去哪下载,为什么装完之后打不开、登录不上,网上找到的汉化包到底怎么用。说实话,这么多年过去,5.3早不算新东西了,可直到… · 2026/9/25 23:51:43
AI自动化工程:系统提示词设计与流水线搭建实战 1. 从"写提示词"到"搭系统":AI自动化工程到底在解决什么问题大多数人接触AI的第一反应是"写个好提示词",然后打开对话框,把需求敲进去,等结果。这个模式在单次任务里够用,但一旦任务变成… · 2026/9/25 23:51:31
传感数据降噪进阶:小波滤波原理、参数调优与工程落地指南 简介:传感数据常夹杂噪声,小波滤波可同时在时频域对信号进行多尺度分析,相比傅立叶变换更适合处理非平稳信号,是传感数据去噪与特征提取的常用手段。面向物联网与传感数据分析初学者,这份资源提供基于Python的一维传感… · 2026/9/25 23:51:25
Atlas 300V 24G推理卡实战:从ONNX转换到YOLO多路视频流部署 先说结论,直接回答标题下面那个被搜了很多次的问题:Atlas 300V 24G确实是一块运算加速卡,而且它在整个Atlas产品线里的定位非常清楚——推理卡。前阵子我在生产环境里用这块卡把YOLOv5的检测服务重新部署了一遍,从模型转换、驱动安… · 2026/9/25 23:51:06
Atlas 300V 24G推理加速卡上部署YOLO实战指南 Atlas这个词最近在技术社区里又热了一波,和它绑定的两个问题分别是"atlas部署yolo"和"atlas 300v 24g 是运算加速卡吗"。如果你也是冲着"AI推理加速"这几个字进来的,我先给个结论:Atlas 300V 24G确实是运算加速… · 2026/9/25 23:51:00
PyInstaller 打包原理与工程化避坑指南 简介:本资源为PyInstaller早期版本(0.1.4)的源码安装包,面向Python初学者与轻量级打包需求者,解决本地环境快速部署PyInstaller工具、理解其底层结构及定制化打包逻辑的问题。压缩包共19个文件,含5个核心Py… · 2026/9/25 23:50:16
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37