Pandas数据处理全流程:从DataFrame清洗到分组聚合实战
在 Python 数据分析这个圈子里摸爬滚打这些年我越来越觉得有个说法特别对如果你只打算学一个库做数据处理那必须是 Pandas。不管你是刚从 Excel 转到 Python 的新手还是已经在写爬虫、跑机器学习模型的开发者到最后跟表格数据打交道的时候几乎都会撞到 Pandas 这堵墙上。而且一旦你用顺了手就再也回不去了。Pandas 之所以被称为 Python 三大基本库之一另外两个自然是 NumPy 和 Matplotlib是因为它把所有你在 Excel 里能做的操作——筛选、排序、透视、关联、清洗——都搬到了代码里还捎带手解决了一些 Excel 根本做不了的事比如处理几百万行的数据不卡死比如把清洗过程完整记录下来以便复现。这篇文章我不打算堆 API 文档而是从一个实际项目的数据处理需求出发把 Pandas 里最常用的核心功能串一遍说清楚每个操作解决什么问题、为什么这么用以及在真实场景里你会踩到哪些坑。1. 为什么 Pandas 是绕不开的那个库1.1 数据工作流里的位置很多人一开始接触数据分析用的工具可能是 Excel、WPS甚至 Google Sheets。这些工具在数据量小、格式规整的时候确实舒服鼠标点两下就能出个透视表。但一旦数据到了几十万行、上百个字段或者你需要每天重复做同一套处理流程的时候表格软件就开始力不从心。而 Pandas 的核心定位就是给 Python 提供一套高效、灵活的数据结构和操作接口让你能够把“读取数据—清洗数据—分析数据—输出结果”这一整个流程全部代码化。我在某公司做销售数据复盘的时候接过一个特别典型的任务下游团队每周一早上需要一份上周各区域的订单汇总表包括订单量、销售额、退货率、客户分布这几个维度。原始数据呢是从企业系统里导出的 CSV 和 Excel 文件编码格式混乱、日期列有两种格式、有重复记录、还有一堆空值。要是在 Excel 里手工处理每周至少要耗一上午而且每次处理方式还不完全一样容易出错。后来我用 Pandas 写了套脚本每周一只需要跑一遍十分钟出结果而且输出文件的格式、表头、汇总方式每次都一模一样。这个例子能说明 Pandas 在数据工作流里的位置它不是用来做复杂建模的而是用来做数据处理中“最脏最累最繁琐”的那部分。它的重点在于数据准备和特征工程这是任何数据分析、可视化、机器学习项目都要经过的第一步。如果你把整个项目比作做饭Pandas 不是掌勺的那个大厨那是模型算法也不是摆盘的那个那是可视化库而是负责洗菜、切菜、配菜的帮厨——没有它后面的环节全是空中楼阁。1.2 和 NumPy 的关系提到 Pandas就绕不开 NumPy。Pandas 的底层数据存储和计算大量依赖 NumPy 的数组结构尤其是数值型列本质上就是一个个 NumPy 数组。学 Pandas 之前稍微懂一点 NumPy 当然更好但如果你直接用 Pandas其实也没太大问题。因为 Pandas 已经把绝大多数数组操作封装成了更直观的表格操作方式。举个最简单的例子一个二维数组在 NumPy 里你要记着 axis0 是行、axis1 是列操作起来总要在脑子里转一道弯。但在 Pandas 里你可以直接通过列名df[销售额]去取数据通过行标签df.loc[2024-01-01]去取数据语义清晰得多。Pandas 在 NumPy 之上加的两个东西是最宝贵的一个是轴标签行索引和列名另一个是对齐功能。轴标签让你可以用名字而不是下标去访问数据对齐功能则让你在做两个表加减乘除的时候自动按标签对齐而不是按位置生硬地对应。2. 核心数据结构Series 与 DataFrame2.1 Series带标签的一维数组我们直接从最基础的数据结构开始讲。Series 你可以理解成一个带标签的一维数组它由两部分组成左边是索引index右边是值values。你可以把它类比成一个带行号的 Excel 单列不过这个行号不一定是整数可以是字符串、日期甚至是自定义的标签。创建一个 Series 很简单import pandas as pd s pd.Series([10, 20, 30], index[a, b, c]) print(s)输出结果a 10 b 20 c 30 dtype: int64这里最值得注意的就是索引的作用。你可以通过标签s[b]取值也可以通过位置s.iloc[1]取值。当你需要对两个 Series 做运算时Pandas 会自动根据索引对齐。比如s1 pd.Series({a: 1, b: 2, c: 3}) s2 pd.Series({b: 4, c: 5, d: 6}) print(s1 s2)结果会是 a 列变成 NaN因为 s2 里没有 ad 列也是 NaN因为 s1 里没有 d。这个对齐行为在某些场景下非常方便但也容易让新手困惑。你需要记住一个原则在 Pandas 里运算结果的索引是两个输入索引的并集缺失的部分用 NaN 填充。2.2 DataFrame二维表格的载体DataFrame 是 Pandas 里最常用的数据结构你可以把它想象成一张 Excel 表或者数据库里的一张表。它由行索引、列名和单元格数据组成。一个 DataFrame 可以包含不同类型的列——整数列、浮点数列、字符串列、日期列——这在真实数据里非常常见。从字典创建 DataFrame 是最直观的方式data { 姓名: [张三, 李四, 王五], 城市: [北京, 上海, 广州], 销售额: [1200, 3400, 2800] } df pd.DataFrame(data) print(df)输出姓名 城市 销售额 0 张三 北京 1200 1 李四 上海 3400 2 王五 广州 2800这个时候你就拥有了一个结构清晰的数据表。注意如果你不指定索引Pandas 会自动生成从 0 开始的整数索引也就是图中左侧那一列 0、1、2。在真实项目中DataFrame 最常见的来源不是手动从字典创建而是从文件读取。比如pd.read_csv(sales.csv)读 CSVpd.read_excel(report.xlsx)读 Excel。这也是 Pandas 最强大的地方之一一行代码就能把磁盘上的数据文件加载成内存里的表格对象。2.3 常用的数据查看与检查方法拿到一个 DataFrame 之后别急着处理先做点基本检查。我每次拿到数据集都会按固定套路走一遍# 查看前几行确认数据长什么样 print(df.head()) # 查看每列的数据类型、非空值数量 print(df.info()) # 查看数值列的统计摘要均值、标准差、最小值、最大值、分位数 print(df.describe())这三个命令基本够你决定下一步怎么处理了。df.info()尤其重要它会告诉你每一列是不是有缺失值类型是什么。比如某列显示object那这一列大概率是字符串如果某列是datetime64那说明已经被识别成了日期时间类型。如果你发现一张表有 10 万行数据但某列非空值只有 8 万那这一列就有 2 万个空值需要处理。3. 数据读取与写出你绕不开的文件操作3.1 读取 CSV最基础也最容易出问题读取 CSV 的 API 是pd.read_csv()这个函数我用了不下上千次但每次都不敢说不会踩坑。以下三点是实际项目中碰到过的典型问题编码问题。CSV 文件的编码最常用的有 UTF-8、GBK中文 Windows 系统导出的老文件常见和 UTF-8-BOM。如果你读到一个文件报 UnicodeDecodeError十有八九是编码搞错了。解决方法很简单df pd.read_csv(data.csv, encodinggbk) df pd.read_csv(data.csv, encodingutf-8-sig)我的经验是遇到中文 CSV 文件报编码错误GBK 的成功率很高如果是 Excel 另存的 CSV试试 UTF-8-SIG。分隔符问题。有些文件表面上是 CSV实际上用的是分号、制表符或者逗号和引号混用。你可以显式指定分隔符df pd.read_csv(data.tsv, sep\t) df pd.read_csv(weird.csv, sep;)如果分隔符是多字符或规则比较复杂还可以用正则表达式sep\s来按任意空白字符分割。列名问题。如果原始文件第一行不是列名你需要设置headerNone然后自己给列取名df pd.read_csv(data.csv, headerNone, names[列1, 列2, 列3])这个操作在读取没有表头的日志文件、导出文件时特别常见。3.2 读取 Excel多个 sheet 和指定列Excel 文件的读取用pd.read_excel()它依赖另一个库 openpyxl对 .xlsx 格式或者 xlrd对老式 .xls 格式。实际工作中最容易遇到的情况是一个 Excel 文件里有多个 sheet你需要读其中某一个。df pd.read_excel(report.xlsx, sheet_name华东区)如果你不指定 sheet_namePandas 默认读取第一个 sheet。另一个常见需求是只想读某几列可以配合usecols参数usecols[姓名, 销售额]或usecolsA:C。提示处理大 Excel 文件时要留意内存占用。.xlsx本身就是压缩包格式解析起来比 CSV 慢不少。如果同一个数据有 CSV 版本优先读 CSV。3.3 写出文件to_csv 和 to_excel 的细节处理完数据输出结果也同样重要。df.to_csv(output.csv, indexFalse)是最常用的写法。这里indexFalse必须牢记如果不加Pandas 会把行索引也写进文件生成一个多余的“序号列”很多下游工具打开文件后会莫名其妙多出一列。df.to_excel(output.xlsx, indexFalse, sheet_name结果)也是同理。如果你想在一个 Excel 文件里写多个 sheet可以用pd.ExcelWriterwith pd.ExcelWriter(all_results.xlsx) as writer: df1.to_excel(writer, sheet_name汇总, indexFalse) df2.to_excel(writer, sheet_name明细, indexFalse)这个用法在生成周报、月报时非常实用——一个文件里既放汇总表又放明细表下游同事打开就能对照着看。4. 数据清洗真实项目里 80% 的时间都花在这4.1 缺失值处理不是无脑删也不是无脑填数据清洗是 Pandas 应用中最核心的场景。没有脏数据是清洗不了的而缺失值是最典型的脏数据形态。缺失值在 Pandas 里显示为 NaNNot a Number判断缺失值有两个常用方法df.isna()返回布尔矩阵df.isna().sum()能按列统计缺失数量。处理缺失值常规策略有三条路第一种直接删除缺失行。df.dropna()在缺失值不多、并且这些行本身也没有太大分析价值的时候适用。不过如果你一行数据里有 80% 的字段是空的那么哪怕只是某几个关键列缺失删掉那部分数据也说得过去。我会加个subset参数只对关键列判断df_clean df.dropna(subset[订单号, 销售额])第二种填充一个特定值。df.fillna(0)常用于数值型列比如销售额缺失时可以填 0因为缺失可能意味着没有成交。df.fillna(未知)常用于字符串列比如客户名称缺失时填“未知”。第三种用统计值填充。数值型列缺失时可以用均值、中位数替换df[销售额] df[销售额].fillna(df[销售额].median())这里用中位数而不是均值是因为销售额这类数据通常有长尾少数大额订单会把均值拉高用均值填充会引入偏差。关于缺失值的处理我有一条实操原则处理前先统计缺失比例。如果某列缺失比例超过 60%这列信息量就非常有限了直接考虑删除整列不是非得填充。4.2 重复值处理要看你怎么定义“重复”重复值的处理比很多人想得复杂因为“重复”的定义可能是全行重复也可能是某几列重复。全行去重很简单df.drop_duplicates()。但实际项目中更需要的是“按关键列去重”比如同一张订单号可能出现多行但全行并不完全一致比如有一列是备注每次扫描时间不同。这时候你这样写df df.drop_duplicates(subset[订单号])这条语句会保留每个订单号第一次出现的那一行其余全删。如果你不只关心第一次出现的还想根据某列排序后保留最新记录需要先排序再去重df_sorted df.sort_values(导入时间, ascendingFalse) df_unique df_sorted.drop_duplicates(subset[订单号], keepfirst)这个模式在业务系统导出数据、日志数据合并的时候非常常用我愿称之为“手动实现数据库窗口函数的穷人版”。4.3 数据类型转换字符串数字永远是重灾区从外部文件读进来的数据经常会出现一种情况明明看起来是数字但 Pandas 里那一列的类型是 object字符串。比如“销售额”列因为你读取的 CSV 里混入了空值Pandas 只能把整列识别成字符串。此时你直接做df[销售额].sum()会得到一堆数字拼接起来的字符串。解决方法df[销售额] pd.to_numeric(df[销售额], errorscoerce)errorscoerce的含义是无法转换为数字的值变成 NaN。这是在数据清洗中被频繁用到的一个参数。如果没有它一旦数据里有类似“1,200”带千分位逗号或者“1200元”这样的格式整个转换过程就会报错。处理带千分位逗号的字符串更优雅的方式是df[销售额] df[销售额].str.replace(,, , regexFalse).astype(float)处理日期时间也是同样的逻辑。pd.to_datetime()是另一张王牌它能把各种格式的日期字符串统一转换成 datetime64 类型df[下单日期] pd.to_datetime(df[下单日期], format%Y/%m/%d)format参数指定原始字符串格式转换速度会快很多。如果你不确定格式也可以不传这个参数Pandas 会尝试自动推断但速度会慢而且偶尔会有解析错位的情况比如月和日搞反。4.4 字符串操作.str 接一切Pandas 的字符串方法通过.str访问器调用。你可能会问这个.str是什么意思简单说就是告诉 Pandas接下来我要对这一列做字符串操作。常用的有df[城市].str.contains(上海) # 是否包含某个子串 df[姓名].str.strip() # 去除首尾空格 df[电话].str.replace(-, , regexFalse) # 替换字符 df[城市].str.upper() # 转为大写 df[城市代码].str.extract(r(\d{3})) # 用正则提取子串这些方法用熟了之后很多原本需要写循环的字符串清洗任务一行代码就完成了。4.5 条件筛选布尔索引是最常用的操作条件筛选几乎是每天都要用的功能。举几个典型场景# 筛选销售额大于 1000 的订单 df[df[销售额] 1000] # 多条件筛选且 df[(df[销售额] 1000) (df[城市] 上海)] # 多条件筛选或 df[(df[城市] 上海) | (df[城市] 北京)] # 筛选城市在列表中的行 df[df[城市].isin([上海, 北京, 广州])]这里有个新手最容易犯的错多条件筛选时必须用而不是and否则会报“布尔值不明确”的错误。同时每个条件都要用括号括起来因为 Python 的运算符优先级会导致结果不符合预期。筛选之后配合赋值就能实现“按条件修改数据”的效果df.loc[df[销售额] 10000, 订单等级] VIP这句代码的意思是找到销售额大于 10000 的那些行在这些行的“订单等级”列上赋值为“VIP”。5. 分组聚合GroupBy 的威力5.1 从 Excel 透视表到 groupby如果你用过 Excel 的透视表Pandas 的groupby你一定会快速上手。它们的思想是一样的对数据按某个或某几个维度分组然后在组内做聚合计算比如求和、平均、计数。result df.groupby(城市)[销售额].sum() print(result)这句代码的运行逻辑是先按“城市”列分组同一个城市的所有行归到一组然后计算每个组内“销售额”的总和。输出的结果中城市变成索引销售额变成聚合值。多维度分组也非常常见result df.groupby([城市, 商品类别])[销售额].sum()这时你会得到一个两层索引的 Series第一层是城市第二层是商品类别。如果你想把这两层索引展开、变成跟 Excel 透视表一样的宽表可以调用result df.groupby([城市, 商品类别])[销售额].sum().unstack()unstack()会把内层索引变成列名行是城市列是商品类别每个单元格是销售额。如果你熟悉 Excel 透视表这时你已经能找到完全对应的感觉了。5.2 聚合函数的多种用法groupby之后可以接的聚合函数很多常见的有sum()、mean()、count()、max()、min()、median()、std()。但你不需要反复写分组代码result df.groupby(城市).agg({ 销售额: sum, 订单号: count, 利润率: mean })用字典指定不同列的聚合方式一次分组就能同时算出多个统计量。如果你想知道每个分组里所有数值列的汇总统计还可以用describe()df.groupby(城市).describe()这个操作会一次性输出每个城市在数值列上的均值、标准差、最小值、25% 分位数、中位数、75% 分位数、最大值、计数非常节省时间。5.3 transform组内运算的隐藏利器transform可能不如agg常用但在某些场景下非常关键。它的特点是返回的结果和原 DataFrame 行数相同而不是聚合后的行数。比如你想给每个订单计算“该订单销售额占所属城市的比例”df[城市销售总额] df.groupby(城市)[销售额].transform(sum) df[城市占比] df[销售额] / df[城市销售总额]这里每个订单行都会得到自己所在城市的销售总额然后一列除一列就得到了占比。如果用agg来做这一步还需要重新 join 回去而transform直接帮你搞定了。还有一个典型用法是组内填充缺失值——用每个城市自己的平均值去填充该组内缺失的销售额df[销售额] df[销售额].fillna(df.groupby(城市)[销售额].transform(mean))这个思路非常实用比全表用均值填充要合理得多。6. 透视表与交叉分析pivot_table 的实战6.1 pivot 和 pivot_table 的区别Pandas 提供两个和“透视”相关的函数。df.pivot()要求数据已经清洗好、没有重复行它纯粹是重新组织行列结构。df.pivot_table()则更宽容它允许重复行存在并且会对重复部分做聚合计算。项目中最常用的是pivot_table。它的核心参数有这么几个index是“行维度”columns是“列维度”values是要计算的数值列aggfunc是聚合方式。来看一个具体的例子。假设你有一份订单明细表每个城市有多个商品类别你想快速看一张“城市 x 商品类别”的销售额矩阵pivot pd.pivot_table( df, index城市, columns商品类别, values销售额, aggfuncsum, fill_value0 )fill_value0会把那些“某城市没有某商品类别销售额”的空单元格填成 0这样生成出来的表格没有空值打印出来的观感会非常干净。6.2 多级透视与边际汇总pivot_table也支持多维度和边际汇总pivot pd.pivot_table( df, index[城市, 渠道], columns[商品类别], values[销售额, 订单数], aggfunc{销售额: sum, 订单数: count}, marginsTrue, margins_name合计 )marginsTrue会在末尾生成一行“合计”并且最右侧也会生成一列“合计”。这个功能相当于 Excel 透视表里的“总计”行/列。带合计的透视表在出周报时特别有用直接拿一张表就能对整体和分项一目了然。6.3 交叉表crosstab 的快捷用法pd.crosstab()和pivot_table类似但它天生是为“计数”设计的。比如你要看不同城市不同商品类别的订单数量分布cross pd.crosstab(df[城市], df[商品类别])这条语句直接生成行是城市、列是商品类别的频数表。它可以传入normalizeTrue把计数转成占比或者传values和aggfunc做自定义聚合。crosstab 在处理分类变量的交叉分析时非常顺手尤其是在做用户画像、渠道分析、产品分析这类场景。7. 数据合并与连接join、concat、merge7.1 merge数据库风格的表连接在真实项目中数据很少只存在一张表里。比如订单表里有订单金额客户表里有客户姓名你想把两张表的信息拼在一起就要用pd.merge()。它相当于 SQL 里的 JOIN。merged pd.merge(order_df, customer_df, on客户ID, howleft)on参数指定连接键how参数指定连接方式inner取两表交集、left左表保留全部、right右表保留全部、outer两表全部保留缺失部分用 NaN。我自己的项目经验是绝大多数场景用howleft。因为通常主表是订单明细客户表是维度表我们需要保证订单行一条不丢然后去匹配客户信息。7.2 concat简单粗暴地拼接数据pd.concat()用来拼接两个结构相同列名一致的 DataFrame。最常见的场景是每个月的数据存一个 CSV到年底要做全年汇总那就要把 12 个表纵向拼起来。all_data pd.concat([df1, df2, df3], ignore_indexTrue)ignore_indexTrue表示拼接后重新生成从 0 开始的索引否则原来的索引会被保留可能出现重复索引值。这个细节一定不能漏。7.3 join按索引连接如果两张表是按行索引而不是具体列关联的可以用df1.join(df2)。这个方法在时间序列对齐的场景比较常见比如你有两个不同来源的日度数据索引都是日期想按日期对齐拼接直接用 join 就很方便。df_all df_price.join(df_volume, howinner)8. 排序与排名让数据有秩序8.1 排序的两种方式df.sort_values()是最常用的排序函数df_top df.sort_values(销售额, ascendingFalse)如果你需要先按城市排序再按销售额降序df_sorted df.sort_values([城市, 销售额], ascending[True, False])还有一种情况是按索引排序比如你做了groupby之后得到的结果是按索引排列的或者日期索引乱了df_sorted df.sort_index()8.2 排名rank 的几种策略排名和排序容易混淆。排序是把行调换顺序排名是新增一列给出每个值的大小次序。比如一场促销活动的订单你想要“金额从高到低”的排名df[金额排名] df[销售额].rank(ascendingFalse, methoddense)第一个参数ascendingFalse表示金额越大排名越靠前。第二个参数method有几种取值average默认相同值取平均名次比如两个第二名并列就都是 2.5、min并列时取最小名次比如两个第二名并列都是 2、dense并列后下一个名次紧接比如两个第二名并列后第三名就是 3中间不断档。实际业务中dense用得多一些因为名次不会出现跳跃后端同事拿到数据也更容易处理。9. 时间序列处理日期数据分析的必修课9.1 设置日期索引和重采样时间序列在 Pandas 里有专门的玩法。首先把日期列转成 datetime 类型再设置为索引df[日期] pd.to_datetime(df[日期]) df df.set_index(日期)设置完索引之后你就能按时间范围切片df[2024-01-01:2024-01-15]也能按月/季度/年做重采样聚合# 按月汇总销售额 df.resample(M)[销售额].sum()resample(M)按自然月分组W按周、Q按季度、Y按年。做个简单的日度销售转月度销售报表一条resample就搞定了。9.2 时间偏移与滞后特征如果你想生成“上一周期”的特征比如做增长分析时计算环比需要用到shift()df[上月销售额] df[销售额].shift(1)shift(1)把整列数据往下移动一行。如果你移动后想要计算环比增速直接对两列做除法就行。注意移动后第一行会是 NaN因为它在数据之前没有“上个月”的对应值。这个操作在金融、零售、运营数据分析中极其常见。10. 性能优化思路处理大数据时的保命技能Pandas 对中小数据量几百万行以内非常顺手但一旦数据量上了亿级就明显吃力。不过在绝大多数实际业务场景里我们还没到需要换大数据引擎的程度做好下面几件事就能有效规避卡顿和内存溢出。10.1 用对数据类型Pandas 默认用 64 位整数和浮点数存储数值列但很多时候数据根本不需要这么大的范围。比如年龄列、订单状态码完全可以用更小的类型节约内存。df[年龄] df[年龄].astype(int8) df[性别] df[性别].astype(category)使用 category 类型压缩重复度高的字符串列比如城市、性别、商品类别内存占用会大幅下降。这也是为什么在很多数据集上先做类型压缩再处理内存能省 50% 以上。10.2 按需要读取数据pd.read_csv()支持usecols参数只读取需要的列在列特别多比如导出表有 200 列实际业务只用到 5 列的时候这是提速和降内存最直接的方式df pd.read_csv(big.csv, usecols[订单号, 销售额, 日期])10.3 向量化操作代替循环如果你发现自己写了个 for 循环在你 Pandas 代码里停一下思考几秒钟。Pandas 的杀手锏之一就是“向量化”——一次对一整列做操作而不是一行一行算。循环 100 万行数据可能需要几秒甚至几十秒而向量化操作往往在毫秒级就完成了。比如你要根据销售额给订单分级新手可能写# 不推荐的写法 levels [] for value in df[销售额]: if value 10000: levels.append(VIP) elif value 5000: levels.append(重点) else: levels.append(普通) df[等级] levels向量化的写法只要一行df[等级] pd.cut(df[销售额], bins[0, 5000, 10000, float(inf)], labels[普通, 重点, VIP])这其中的差别在数据量大时是几十倍的性能差距。我在处理几十万行订单数据时体会很深用循环跑可能要几分钟改成向量化操作不到一秒就出结果。10.4 适当使用 inplace 参数Pandas 大多数操作默认返回一个新对象不会修改原 DataFrame。比如df.dropna()如果你不赋值回去实际上是白操作了。如果你确定要在原对象上修改可以加inplaceTrue比如df.dropna(inplaceTrue)。不过我的习惯是尽量少用inplace而是写成df df.dropna()。这样可以更明确地表达“原表被替换成新表”避免调试时一头雾水。11. 常见报错与排查清单11.1 高频报错逐个数SettingWithCopyWarning这大概是新手遇到最多的警告。它的出现场景通常是从一个 DataFrame 切片出子 DataFrame然后给子 DataFrame 的某列赋值。Pandas 没法确定你是想改原表还是改副本所以会警告。最直接的解法是如果你确实要修改原表用df.loc而不是链式赋值如果你只想操作副本先.copy()一份再改。sub_df df[df[城市] 上海].copy() sub_df[备注] 测试ValueError: 布尔值不明确这个错误的典型触发点是用if df[销售额] 1000:来判断整个列但一列里有多个值没法确定整体是 True 还是 False。你应该用df[df[销售额] 1000]做筛选而不是在 if 里做判断。KeyError访问不存在的列名时会出现。排查思路是先用df.columns打印出所有列名检查是不是有空格、大小写不一致等问题。Excel 导出的数据列名经常带着不可见空格你看着像“姓名”实际是“姓名 ”。内存不足下载了 10 GB 的 CSV然后pd.read_csv直接崩了。这时先用usecols只读需要字段再在读取时指定dtype能有效降低内存。Dask、Polars 这些工具可以处理更大数据但对大多数需求来说能靠压缩数据类型解决的问题先不急着换工具。11.2 一个典型的数据处理全流程串烧把前面讲的内容串起来一个典型的项目处理流程是# 1. 读取 df pd.read_csv(订单明细.csv, encodinggbk) # 2. 检查 print(df.info()) print(df.head()) # 3. 清洗 df[订单日期] pd.to_datetime(df[订单日期]) df[销售额] pd.to_numeric(df[销售额], errorscoerce) df df.drop_duplicates(subset[订单号]) df df.dropna(subset[订单号, 销售额]) # 4. 分析 city_summary df.groupby(城市)[销售额].sum().reset_index() city_pivot pd.pivot_table(df, index城市, columns商品类别, values销售额, aggfuncsum, fill_value0) # 5. 输出 with pd.ExcelWriter(月度报告.xlsx) as writer: city_summary.to_excel(writer, sheet_name城市汇总, indexFalse) city_pivot.to_excel(writer, sheet_name产品透视, indexFalse)这段代码看着不长但它几乎覆盖了 Pandas 在真实业务里 90% 的应用场景。你如果能在没有文档的情况下把每一步都写出来说明这套工具你已经真正掌握了。12. 给刚上手 Pandas 的朋友几条实践建议有些东西是 API 文档不会告诉你的但它们往往比语法更重要。建议从每天处理一份真数据开始。无论是课程作业、实习报告、自己爬的数据、业务系统的导出表先拿 Pandas 跑一遍“读取—清洗—分析—输出”全流程。看十遍教程不如自己动手跑一次几十万行的真实数据报的错、踩的坑才是最快的老师。不要死记 API学会查文档。Pandas 的 API 太多了没有人能把所有函数参数记全。我自己也经常打开官方文档或者用dir(df)去看看某个对象有哪些方法。真正重要的是你对“要做成什么样”有清晰的思路剩下的是找到对应函数的问题。读懂错误信息比重新搜代码更高效。新手看到报错第一反应是复制粘贴去搜索报错文本这当然可行。但更快的办法是先读一遍错误信息它一般会精确告诉你是哪一行、哪个列名、什么类型出了问题。错误处理能力跟读代码能力是正相关的。建立自己的代码片段库。我自己的脚本里长期保存着“读 CSV 并处理编码”“日期列标准化”“分组汇总输出 Excel”这几个常用片段。项目做得多了你会发现很多数据处理任务本质上是这几个片段的排列组合。把这几个基础动作练到肌肉记忆后面所有项目都会顺很多。Pandas 这个库真正让我觉得厉害的地方在于它把 Excel 的易用性和代码的自动化结合在了一起。它不会让你变成一个算法高手但它会让你成为一个真正能解决问题的人。而且现在 Python 生态里围绕 Pandas 的扩展——比如 Polars 对标它的性能、Pandas 2.0 对 PyArrow 后端的支持、pandera 做数据校验——都在说明一个问题Pandas 在一个又一个数据项目里已经成了那个绕不开的起点。先把 Pandas 的流程跑通后面的路就好走多了。

相关新闻

SpringBoot构建社区二手回收平台的技术实践

SpringBoot构建社区二手回收平台的技术实践

1. 项目背景与核心价值去年帮学校环保社团做二手物品回收系统时,发现市面现有平台普遍存在两个痛点:一是交易流程冗长导致闲置物品周转率低,二是缺乏社区化运营使得用户粘性不足。这个基于SpringBoot的VE社区二手回收平台(版本20b…

2026/10/15 9:55:50 阅读更多 →
STM32 PID温控实战:从输出映射到参数整定的全过程

STM32 PID温控实战:从输出映射到参数整定的全过程

简介:STM32单片机PID加温项目调试经验文档,面向嵌入式开发人员,解决温度控制中PID参数整定与代码落地问题。内容从实际项目出发,先说明PID加热原理:当实际温度低于目标值约5℃时启用PID运算,定时器1每2秒计…

2026/10/15 9:55:50 阅读更多 →
校园考研论坛小程序开发实战:Python+Django+Uniapp技术解析

校园考研论坛小程序开发实战:Python+Django+Uniapp技术解析

1. 项目概述:校园考研论坛的移动化实践作为一名经历过考研的开发者,我深知备考过程中信息交流的重要性。传统的考研QQ群和贴吧存在信息杂乱、难以沉淀优质内容的痛点。去年我用PythonDjangoVue.js开发过网页版考研论坛,但发现学生更习惯使用移…

2026/10/15 9:55:50 阅读更多 →

最新新闻

学Simulink——储能变流器(PCS)中 PWM 整流器的恒流充放电(CC Charge / CC Discharge)仿真

学Simulink——储能变流器(PCS)中 PWM 整流器的恒流充放电(CC Charge / CC Discharge)仿真

目录 手把手教你学Simulink——储能变流器(PCS)中 PWM 整流器的恒流充放电(CC Charge / CC Discharge)仿真 一、为什么储能 PCS 要做 恒流(CC)充放电双向 PWM 整流器 二、PCS 双向控制与 CC 模式原理** 2.1 功率平衡估算(用于 idref​折算) 2.2 模式定义 三、关键…

2026/10/15 10:38:32 阅读更多 →
TaoToken 视角下的示波器使用:measure/acquire/storage/cursor 四步实测

TaoToken 视角下的示波器使用:measure/acquire/storage/cursor 四步实测

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 10:38:32 阅读更多 →
学Simulink——三相 PWM 整流器在船舶岸电系统(Shore-to-Ship Power, Cold Ironing)中的并网控制仿真

学Simulink——三相 PWM 整流器在船舶岸电系统(Shore-to-Ship Power, Cold Ironing)中的并网控制仿真

目录 手把手教你学Simulink——三相 PWM 整流器在船舶岸电系统(Shore-to-Ship Power, Cold Ironing)中的并网控制仿真 一、为什么船舶岸电系统要用 三相 PWM 整流器/并网变流器 二、岸电系统典型参数(教学模型)** 三、Simulink 建模(手把手)** 3.1 Step 1️⃣ —— 港…

2026/10/15 10:38:32 阅读更多 →
PP-HumanSeg Lite + NCNN C++ 部署实战:精准版本对齐与边缘落地

PP-HumanSeg Lite + NCNN C++ 部署实战:精准版本对齐与边缘落地

简介:本资源是一套面向嵌入式与移动端开发者的轻量级人像分割部署方案,聚焦PP-HumanSeg Lite模型在NCNN框架下的C端高效落地,适用于视频会议背景虚化、AR换装、实时抠图等低延迟场景,适合具备C基础和一定CV部署经验的中高级开发者…

2026/10/15 10:38:32 阅读更多 →
OpenGL正背面剔除与深度测试:原理、配置与穿模问题排查

OpenGL正背面剔除与深度测试:原理、配置与穿模问题排查

1. 从一个“穿模”现象说起:为什么需要正背面剔除与深度测试但凡做过3D渲染的人,几乎都遇到过这样的场景:一个封闭的立方体或者角色模型,旋转到某个角度后,本该被挡住的背面却透了出来,或者两个物体交叠的地…

2026/10/15 10:38:32 阅读更多 →
企业WordPress定制开发:核心价值与选型指南

企业WordPress定制开发:核心价值与选型指南

1. 为什么企业需要专业的WordPress定制开发服务 在数字化浪潮席卷各行各业的当下,企业官网已从简单的"电子名片"升级为集品牌展示、客户服务和业务转化于一体的核心平台。WordPress作为全球占比43%的内容管理系统,凭借其开源特性、丰富的插件生…

2026/10/15 10:37:31 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →