ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

pandas数据处理全指南:从入门到实战

pandas数据处理全指南:从入门到实战 1. 写在前面为什么你一定要学pandas如果你刚接触Python或者已经写了几天代码准备往数据分析方向走那pandas一定是绕不开的那个库。我可以直接告诉你一个判断标准在Python的数据处理生态里pandas就是那个“事实标准”。你去看招聘要求也好看别人做的数据分析项目也好爬虫之后的数据清洗也好几乎全部都会出现pandas的身影。那pandas到底能做什么说白了它就解决一个问题让Python能够像操作Excel表格一样在代码里处理结构化数据。你在Excel里能做筛选、排序、求和、透视pandas全都能做而且是用代码来做这意味着你可以批量处理、自动重复、一键跑完整个流程。同样的工作用Excel点点点可能要半小时写一段pandas脚本三秒钟搞定。这就是它的核心价值——把“人肉操作表格”变成“程序自动处理表格”。这篇内容我打算完全按照我的实际操作经验来写。我既不会照着官方文档给你念一遍API也不会像某些教程那样只丢一堆代码让你自己看。我会告诉你pandas里的每个核心概念到底解决什么问题每个操作在真实项目中会在什么场景用到以及我这些年用pandas踩过的坑、养成的习惯全部一次讲清楚。这篇内容会很长因为我希望你看完不只是“知道pandas”而是真的“能上手用pandas”。内容适合的人群我也说一下已经会Python基础语法变量、列表、字典、for循环、函数想往数据分析、数据清洗或者自动化办公方向走的同学。如果你是完全的编程零基础建议先花一周把Python基础语法过一遍再回来看这篇不然你可能会卡在语法上而不是pandas本身。2. 环境准备pandas到底怎么装才不出问题2.1 安装之前必须先搞清楚的几件事很多新手一上来就卡在装库这一步而且报错信息五花八门什么ModuleNotFoundError、Requirement already satisfied、pip install pandas执行之后提示找不到pip……这些问题九成都是环境搞混了。什么叫环境搞混就是你电脑上有好几个Python或者你用的Python和pip不是同一个。我先给你一个最简单的验证方法。打开命令行Windows按WinR输入cmd回车Mac打开Terminal输入python --version然后再输pip --version你注意看这两个命令返回的信息。正常情况下它们显示的Python版本应该来自同一个目录。如果python显示的是3.11但pip显示的是3.9的路径那说明你的Windows系统里装了多个Pythonpip装到了另一个Python里import pandas当然就找不到。这个问题特别常见尤其是在Windows上自己从官网下载安装包、然后又装了Anaconda、然后又用VSCode选了别的解释器的同学十个人里面有八个会踩这个坑。所以我给你的第一条建议非常直接不要在系统里瞎装一堆Python。如果你只是为了做数据分析直接装Anaconda全家桶最省事。Anaconda自带Python解释器、自带pandas、numpy、matplotlib等两百多个常用库你学pandas前期根本不需要额外装任何东西打开即用。如果不想用Anaconda觉得太臃肿那就要学会使用虚拟环境venv。每次新建一个项目就创建一个干净的Python环境库装在虚拟环境里不会和系统全局环境冲突。2.2 三种安装pandas的方式对比我直接把三种常用方案整理成对比表你可以根据自己的情况对号入座安装方式适用场景优点缺点Anaconda自带数据分析新手、不想折腾环境的懒人安装完直接用集成了pandas、numpy等核心库软件体积大需要好几个Gpip安装已经有Python环境、不想用Anaconda的朋友轻量、灵活想装什么装什么容易踩环境冲突的坑在IDE里安装PyCharm/VSCode正在用IDE创建项目的新手到进阶用户图形化操作不用记命令有时候IDE选择的解释器和pip不一致如果你是走pip这条路我建议你用下面的命令直接指定国内镜像源下载速度会快很多pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple为什么要指定镜像源因为pandas以及它的底层依赖numpy等库都比较大默认从官方源下载速度可能只有几十KB每秒有时候还会直接超时失败。换成清华源之后基本上几秒钟就能下完。这是最原始的国内开发者被网络逼出来的经验实测非常有效。2.3 验证pandas是否安装成功装完之后怎么确认成功了在命令行进入python交互模式或者直接在IDE里新建一个py文件运行import pandas as pd print(pd.__version__)如果没有任何报错并且打印出来一个版本号比如2.1.0那恭喜你pandas安装成功了。如果你看到的是ModuleNotFoundError: No module named pandas那就说明pandas没有装到当前这个Python环境里。这时候你再去检查一下你现在执行python命令的到底是哪个解释器pip又是装到了哪里对照着把我上面说的方法重新走一遍一般就能解决。注意PyCharm里跑代码之前一定要先看右下角或设置里的Project Interpreter当前选中的解释器是不是你安装pandas的那个。这一步很重要因为PyCharm默认可能会使用它自带的虚拟环境里面根本没有pandas。我看到过太多人卡在这个地方代码明明没问题就是import报错。3. 核心数据结构先把Series和DataFrame吃透3.1 pandas和Excel表格的对应关系装好环境之后第一件要做的事情不是急着跑代码而是先把pandas的两个核心数据结构搞清楚Series和DataFrame。我直接用Excel来类比DataFrame对应Excel里的一张完整表格有行索引、有列名是二维数据。Series对应Excel里的某一行或者某一列是一维数据序列。可以这样理解DataFrame是“列的组合”它的每一列都是一个Series。反过来看DataFrame可以看作由多个Series在纵向上拼起来的结果。把这一层关系搞清楚后面所有的操作你都会觉得顺理成章。我来创建几个最基础的数据结构看看import pandas as pd # 创建一个Series传入一个列表 s pd.Series([10, 20, 30, 40]) print(s) # 创建一个DataFrame传入一个字典 df pd.DataFrame({ 姓名: [张三, 李四, 王五], 年龄: [25, 30, 35], 城市: [北京, 上海, 广州] }) print(df)输出大概是这样0 10 1 20 2 30 3 40 dtype: int64姓名 年龄 城市 0 张三 25 北京 1 李四 30 上海 2 王五 35 广州你注意到没有Series的输出左边那一列0、1、2、3叫索引默认从0开始DataFrame的第一行姓名、年龄、城市是列名左边的一列也是索引。这就是pandas所有操作的基础——通过索引和列名来定位数据。3.2 为什么Series和DataFrame要分开设计刚接触pandas的人可能会不理解既然DataFrame已经能表示表格了为什么还要单独弄一个Series直接用DataFrame不就行了吗这个设计的核心原因其实是大量数据分析场景处理的源头就是一维数据。比如你从接口拿回来一个列表从数据库查出来一列数据你需要统计这批数据的均值、最大值、缺失值情况——这些操作在一维层面上就完成了不需要强行套一个二维表格。而且把DataFrame的一列单独取出来做统计也是一个极其高频的操作。在实际业务里最常见的操作模式是这样的# 取出姓名这一列本质是Series names df[姓名] print(type(names)) # pandas.core.series.Series # 对年龄这一列做统计 print(df[年龄].mean()) # 30.0 print(df[年龄].max()) # 35 print(df[年龄].min()) # 25只要一个Series就能直接调用mean()、max()、min()、sum()这些统计方法非常方便。如果你非要用DataFrame去干这件事反而绕路。所以我的建议是记不住概念没关系但一定要记住这两个东西的存在因为后面所有代码都在跟它们打交道。3.3 DataFrame的创建方式不只是字典传参DataFrame的创建方式其实有很多种除了上面说的传字典之外在实际项目中你还会遇到另外几种常见情况import numpy as np # 从二维列表创建同时指定列名 data [[1, Alice, 90], [2, Bob, 85], [3, Cathy, 92]] df1 pd.DataFrame(data, columns[ID, Name, Score]) # 从numpy数组创建 arr np.array([[1, 2, 3], [4, 5, 6]]) df2 pd.DataFrame(arr, columns[A, B, C]) # 从多个Series拼成DataFrame s1 pd.Series([1, 2, 3], namex) s2 pd.Series([4, 5, 6], namey) df3 pd.concat([s1, s2], axis1)这里面你需要特别注意的是axis1这个参数。很多新手刚学时看到axis1就懵其实可以用一个简单方式理解axis0表示沿着行的方向往下走axis1表示沿着列的方向往右走。你要是记不住就记住这句话——concat时axis0是纵向拼接多行合并axis1是横向拼接多列合并。如果你把方向弄反了很可能会得到一个稀奇古怪的DataFrame。4. 读取数据从Excel、CSV和网页数据说起4.1 pandas怎么读Excel文件大多数人的数据分析生涯是从读Excel开始的毕竟Excel是日常办公里最普遍的数据载体。pandas读Excel用一行代码import pandas as pd df pd.read_excel(销售数据.xlsx)就这么简单文件路径给出pandas就会把整个表格读进来。但是如果你直接运行这段代码很可能会遇到一个报错ImportError: Missing optional dependency openpyxl。这个报错的意思是pandas本身不是一个完全独立的解析器它读取Excel文件需要依赖openpyxl或者xlrd这个第三方库。解决办法也很直接先安装openpyxlpip install openpyxl然后在使用时指定引擎df pd.read_excel(销售数据.xlsx, engineopenpyxl)我觉得这个坑值得多说一句。为什么pandas不把openpyxl直接集成到内部因为pandas的生态策略是保持自身轻量化把不同的文件解析工作交给更专业的库去做。Excel解析交给openpyxlCSV解析就是自带的C语言解析器这样各司其职、维护也方便。理解了这一点你以后再遇到pandas依赖其他第三方库的情况比如读取SQL数据库时依赖SQLAlchemy就不会觉得莫名其妙了。4.2 读取CSV文件以及常见的字符集坑CSV文件的读取更常见因为很多系统导出的数据、网站下载的数据都是CSV格式df pd.read_csv(订单记录.csv)但是CSV有一个极其恶心的点中文乱码。你在本地用Excel打开一个CSV完全正常用pandas一读出来的全是乱码。这是因为CSV文件本身不强制规定编码方式有些文件是UTF-8编码有些是GBK编码如果pandas默认按UTF-8解码而文件实际是GBK编码的那必然乱码。解决办法是手动指定编码df pd.read_csv(订单记录.csv, encodinggbk)如果还是不行试一下另一个df pd.read_csv(订单记录.csv, encodingutf-8)如果还想再保险一点可以试试encodinggb18030这是GBK的超集兼容性更好。我自己的经验是如果客户发给我的CSV是从老系统里导出来的十有八九是GBK编码如果是Python爬虫保存下来的基本都是UTF-8编码。你只要遇到乱码就在这两个编码之间切换基本能覆盖大多数情况。4.3 快速查看数据质量head、info、describe三件套数据读取进来之后先别急着做处理。我强烈建议你先执行三个方法这也是所有老手拿到数据后的“第一眼体检”# 查看前5行快速看下长什么样 print(df.head()) # 查看数据总览有多少行多少列、每列的类型、有没有空值 print(df.info()) # 查看数值列的统计描述均值、方差、最小值、最大值、分位数 print(df.describe())这三个方法输出的信息量很大。head()让你直观看到表格的结构info()告诉你每列的数据类型int64、float64、object如果某列显示object但值看起来是数字那说明这一列被存成了文本后面需要做类型转换describe()直接给出统计信息如果你的数据里有异常值比如年龄列最大值是999在describe里一眼就能看出来。我每次做数据分析项目无论是处理什么数据第一步永远是这三个方法。养成这个习惯之后你对数据的“体感”会强很多。很多新手一拿到数据就开始写各种复杂的处理逻辑结果发现数据本身就有问题白费半天功夫。先体检再动手这是老手和新手的一个关键区别。5. 数据筛选loc、iloc和布尔索引这三件套5.1 loc和iloc到底有什么区别数据读取进来最频繁的操作就是按条件筛选数据。pandas里做筛选最核心的就是loc和iloc。很多人一开始分不清这两个东西。我一句话就能说明白loc是用标签行名、列名来选取数据也就是“按名字找”。iloc是用位置第几行、第几列来选取数据也就是“按第几个找”。来看一段代码import pandas as pd df pd.DataFrame({ 姓名: [张三, 李四, 王五, 赵六], 年龄: [25, 30, 35, 40], 城市: [北京, 上海, 广州, 深圳] }, index[a, b, c, d]) # 自定义行索引 # loc按标签选取取行索引为a的这一行 print(df.loc[a]) # iloc按位置选取取第0行 print(df.iloc[0]) # loc取连续区域从行索引a到c列只取前两列 print(df.loc[a:c, [姓名, 年龄]]) # iloc取连续区域取前3行前2列 print(df.iloc[:3, :2])注意一个特别容易出错的点loc的切片是包含结尾的比如df.loc[a:c]会取到a、b、c三行而iloc的切片和Python原生切片一样是左闭右开的df.iloc[:3]只会取第0、1、2行不包含第3行。我在刚学的时候就被这个搞晕过总是记混。后来我就只记一句话loc是闭区间iloc是开区间。你试试看这个口诀在实战中真的很管用。5.2 布尔索引按条件筛选数据的核心武器比loc和iloc更常用的是布尔索引。什么叫布尔索引就是先得到一个由True和False组成的条件序列然后把它放进方括号里pandas就会只保留条件为True的行。import pandas as pd df pd.DataFrame({ 姓名: [张三, 李四, 王五, 赵六], 年龄: [25, 30, 35, 40], 城市: [北京, 上海, 广州, 深圳] }) # 筛选年龄大于30的人 df_30 df[df[年龄] 30] print(df_30) # 筛选城市是北京的人 df_bj df[df[城市] 北京] print(df_bj) # 多条件筛选年龄大于25且在北上广 df_multi df[(df[年龄] 25) (df[城市].isin([北京, 上海, 广州]))] print(df_multi)这里有几个细节一定要注意第一多条件之间要用且、|或不能用Python的and、or。原因在于df[年龄] 30得到的是一个SeriesSeries之间的逻辑运算只能用、|如果你写and会直接报错The truth value of a Series is ambiguous。这是pandas新手最常见的报错之一。第二多条件时每个条件要加括号。比如df[(df[年龄] 25) (df[城市] 北京)]如果你不写括号Python会因为运算符优先级问题报错或者得到错误结果。我的建议是不管有没有必要每个条件都加括号保证代码清晰可读。第三isin()这个方法适合处理“多个可能取值的匹配”比如你想筛选城市为“北京、上海、广州”三者之一的用户写成一个列表传进去就行不用写三个|连接的条件。5.3 新增列和删除列给表格做“外科手术”筛选之外你一定还会经常需要对列做操作新增一列、删除一列、改列名。这些操作在pandas里都极其简单# 新增一列可以直接用一个列表 df[是否成年] df[年龄] 18 # 新增一列通过计算现有列生成新列 df[年龄加10] df[年龄] 10 # 删除一列 df df.drop(columns[年龄加10]) # 修改列名 df df.rename(columns{姓名: 名字, 城市: 所在城市})关于删除列你可能会在很多老代码里看到df.drop(列名, axis1, inplaceTrue)这种写法。这里我特别多说一句inplaceTrue这个参数在pandas社区里一直存在争议。它是说“原地修改”也就是不返回值直接改掉原来的df。如果inplaceFalse默认drop会返回一个新的DataFrame原df不变。我个人的建议是尽量不要用inplaceTrue。因为它的行为容易让人困惑而且pandas官方已经在多个场合表示未来可能会废弃这个参数。我更推荐你直接用df df.drop(columns[某一列])这种写法显式地把返回值赋给变量逻辑上清楚得多。6. 缺失值与数据类型数据清洗的两座大山6.1 怎么发现缺失值info和isnull的组合拳在真实的数据处理中最让人头疼的不是数据量大而是数据不干净。数据不干净的主要表现之一就是缺失值。Excel里的空单元格导进pandas之后会变成什么答案是NaNNot a Number。注意它不是字符串NaN也不是None而是一个特殊的浮点数标记代表“这个位置没有值”。发现缺失值有几种办法# 一info会直接告诉你每列有多少个非空值 df.info() # 二isnull()把每个位置标记为True/Falsesum()统计每列多少缺失 print(df.isnull().sum()) # 三查看有缺失值的行 print(df[df.isnull().any(axis1)])df.isnull().sum()是我用得最多的一个。它会输出每列有缺失值的个数比如姓名 0 年龄 1 城市 2 dtype: int64这样你一眼就知道哪些列需要处理。这里有个小技巧一定要掌握df.isnull()得到的结果是和原df同样大小的全是True/False的表格sum()统计的是每一列True的个数。这个思路是pandas里很典型的一种模式——先用布尔值标记然后聚合统计。你后面学其他操作时也会反复用到这个套路。6.2 处理缺失值dropna还是fillna这是个选择发现缺失值之后处理方案无非两种删掉或者填上。如果你确定这些缺失值所在的整行数据对分析没有价值可以直接删# 删掉有缺失值的行 df_clean df.dropna() # 只删除某一列上有缺失的行 df_clean df.dropna(subset[年龄])如果你不想删那就填。填什么样的值取决于业务场景# 用固定值填充 df[年龄] df[年龄].fillna(0) # 用这一列的平均值填充 df[年龄] df[年龄].fillna(df[年龄].mean()) # 用前一行或后一行的值填充适用于时间序列 df[温度] df[温度].fillna(methodffill) # 前向填充 df[温度] df[温度].fillna(methodbfill) # 后向填充我之前接过一个做门店销售分析的需求销售金额列里有一些缺失值。我如果用0去填充就会把平均值拉低如果用平均值填充则会掩盖异常的波动。后来我选择了前向填充ffill用上一个已知值去填补这在时间序列数据里算是比较合理的策略。所以你看选择哪种填充方式不是拍脑袋决定的而是要根据数据的业务含义来判断。还有一类处理方式是直接不处理。如果缺失值只占数据总量的不到5%而且这些缺失值不会影响到你具体的统计指标那可以保留。这也是我常用的策略——不是所有数据都得做到完美无缺处理方式的性价比也很重要。6.3 数据类型转换astype和pd.to_datetime数据类型的坑非常隐蔽。我举个例子你用pandas读取Excel里的“编号”列里面的值明明是数字但数据量大时pandas可能把它读成整数也可能读成浮点数有些“日期”列你以为是日期时间类型实际读取后是字符串。这些问题如果不提前发现后面做排序、聚合、画图都会出现莫名其妙的错误。查看数据类型的方法print(df.dtypes)转换数据类型的核心方法# 强制转成int类型 df[年龄] df[年龄].astype(int) # 转成字符串 df[编号] df[编号].astype(str) # 转成日期时间类型 df[下单日期] pd.to_datetime(df[下单日期]) # 转成数值类型如果转换失败会变成NaN df[金额] pd.to_numeric(df[金额], errorscoerce)这里我重点说两个参数。第一个是pd.to_datetime里的format参数。如果你的日期字符串是2024-05-01 12:30:00这种标准格式pd.to_datetime可以直接解析但如果遇到2024/05/01或者01-05-2024这种非标准格式最好手写format%Y/%m/%d来指定速度会快很多也不容易解析错。第二个是errorscoerce。to_numeric在遇到无法转换成数字的字符串时如果设了errorscoerce就会把转换失败的值变成NaN而不是直接报错。这在处理脏数据时特别实用——你先转一遍把非法值变成NaN再用前面讲的缺失值处理方法统一处理数据清洗的过程就能流畅很多。7. 数据聚合与分组从“看数据”到“分析数据”7.1 groupby的用法与底层逻辑当你的数据量达到几千行几万行你不可能一行一行去看。你需要的是“分组统计”比如按城市统计平均销售额、按部门统计人数、按月统计总流水。这些需求在pandas里全靠groupby实现。groupby的底层逻辑其实很简单就是“拆分-应用-合并”Split-Apply-Combineimport pandas as pd df pd.DataFrame({ 城市: [北京, 上海, 北京, 广州, 上海, 北京], 销售额: [100, 200, 300, 150, 400, 250], 成本: [60, 120, 180, 90, 240, 150] }) # 按城市分组计算销售额和成本的总和 result df.groupby(城市).sum() print(result) # 按城市分组计算每个城市的平均销售额 avg_result df.groupby(城市)[销售额].mean() print(avg_result)输出大概是销售额 成本 城市 北京 650 390 上海 600 360 广州 150 90你看groupby(城市)把数据先按城市拆成了若干组然后.sum()对每组进行了求和处理最后pandas自动把所有结果拼成了一整张表。这个过程不需要你写循环一行代码就完成了。这也是pandas相比纯Excel公式的一大优势——你可以在一个连贯的计算流程里把数据处理好。7.2 多列分组和多个聚合函数实际业务中你经常需要按两个维度同时分组。比如按“城市月份”统计销售情况df[月份] [1月, 1月, 2月, 2月, 1月, 2月] result df.groupby([城市, 月份])[销售额].sum() print(result)得到的是一个MultiIndex的Series你可以用result.unstack()把内层索引拆成行或列让它看起来更像Excel透视表。这个操作处理完了再配一个reset_index()就可以很方便地保存到Excel了。如果你想同时算多个统计指标比如每个城市的销售额总和、平均值、最大值result df.groupby(城市)[销售额].agg([sum, mean, max, count]) print(result)agg这个函数非常灵活它支持传列表。你可以在一次groupby操作里把多个聚合函数全部跑完而不需要写多个groupby。这在实际项目中能省下大量时间。7.3 pivot_tableExcel透视表在pandas里怎么用如果你用过Excel的透视表那pandas里的pivot_table你一定觉得非常亲切。groupby是按已有的列分组汇总而pivot_table则更像是把一列的唯一值展开成新的列形成“行列交叉”的矩阵式汇总。比如你要做一张“城市行× 月份列”的销售额透视表pivot pd.pivot_table( df, values销售额, index城市, columns月份, aggfuncsum, fill_value0 ) print(pivot)这个输出格式就和Excel透视表几乎一模一样了。唯一需要留意的是aggfunc参数默认是mean均值但你在完全一样的输入下跑出和预期不符的结果时十有八九是忘了指定aggfunc。我一开始用这个函数好几次都忽略了这一点算出来的数值跟同事对不上后来才发现是均值而不是求和。8. 数据合并与输出把你的处理结果真正落地8.1 concat和merge横向拼还是纵向叠数据处理到后面经常需要把两个表合并成一个。pandas提供了两个核心方法concat和merge。concat适合简单的拼接——两张表结构一样或者形状一致df_a pd.DataFrame({姓名: [张三, 李四], 成绩: [90, 85]}) df_b pd.DataFrame({姓名: [王五, 赵六], 成绩: [92, 88]}) # 纵向拼接把df_b接到df_a下面 df_all pd.concat([df_a, df_b], axis0, ignore_indexTrue)merge适合按某个关键字段进行关联就像SQL里的JOIN。比如一张表存了员工基本信息另一张表存了员工的部门可以通过员工ID关联起来df_info pd.DataFrame({ID: [1, 2, 3], 姓名: [张三, 李四, 王五]}) df_dept pd.DataFrame({ID: [1, 2, 4], 部门: [技术部, 销售部, 财务部]}) # 内连接只保留两边都有ID的行 merged pd.merge(df_info, df_dept, onID, howinner) print(merged)这里的on指定连接的键how指定连接方式inner表示内连接取交集left表示左连接以左边表为基准right和outer同理。如果你只看merge的代码可能觉得抽象可以先在Excel里用VLOOKUP联想一下——merge做的事情就相当于VLOOKUP但功能更强大、更灵活。8.2 to_excel和to_csv把结果保存到文件数据处理完之后最终是要输出的。最常见的两个输出就是写回Excel和CSV# 保存为Excel df.to_excel(处理结果.xlsx, indexFalse, engineopenpyxl) # 保存为CSV df.to_csv(处理结果.csv, indexFalse, encodingutf-8-sig)indexFalse这个参数我每次都会强调因为它的作用是不把行索引写进文件。如果你不指定保存的文件里会多出一列0、1、2……的序号很多时候这不是你想要的结果。encodingutf-8-sig这个参数是针对中文用户的。普通的utf-8编码在Excel中打开CSV时可能中文乱码但utf-8-sig会在文件头部加一个BOM标记Byte Order MarkExcel就能正确识别编码。每当我给别人交付CSV文件时都会用这个编码。如果你用Excel打开了CSV却发现中文是乱码不要怀疑是数据处理错误先检查保存时是否用了utf-8-sig。8.3 一个完整的“读数-清洗-筛选-聚合-输出”小项目掌握了上面的所有知识点之后我们来写一个完整的小案例把pandas常用的操作全部串起来。假设你是一个电商平台的数据分析实习生手里有一份订单记录Excel需要完成以下几件事任务描述读取订单表。删除“订单金额”为空的行。把“下单日期”转为真正的日期时间字段。新增一列“月份”从下单日期里提取出来。按“月份城市”分组求订单总额。筛选出月订单总额超过10万的城市。把结果保存到Excel。完整代码如下import pandas as pd # 1. 读取数据 df pd.read_excel(订单记录.xlsx, engineopenpyxl) # 2. 体检 print(df.head()) print(df.info()) # 3. 删除缺失金额的行 df df.dropna(subset[订单金额]) # 4. 日期转换 df[下单日期] pd.to_datetime(df[下单日期], format%Y-%m-%d) # 5. 新增月份列 df[月份] df[下单日期].dt.month # 6. 按月份和城市聚合 result df.groupby([月份, 城市])[订单金额].sum().reset_index() # 7. 筛选总额大于100000的城市月份组合 high_result result[result[订单金额] 100000] # 8. 输出 high_result.to_excel(高销售城市汇总.xlsx, indexFalse, engineopenpyxl) print(high_result)你仔细看整个流程从读取到体检从清洗到转换从分组聚合到条件筛选最后保存输出这一整套流程就是数据分析师每天都在重复的“标准操作流程”。你在学pandas时不用每个函数都背下来但一定要练熟这条主干流程——它能覆盖日常80%以上的数据处理需求。9. 绕开这些坑我用pandas这几年总结的避坑清单9.1 最常报错的几个原因我见过大量初学者在论坛里求助翻来覆去就是那几个问题。我直接整理成一个速查表你自己对号入座报错信息或现象根本原因解决方案ModuleNotFoundError: No module named pandaspandas没装到当前环境 / 解释器选错检查解释器在正确的环境用pip安装The truth value of a Series is ambiguous在条件里用了and/or改成/ 读Excel时报缺openpyxl缺少Excel解析依赖pip install openpyxl或指定engineopenpyxlCSV中文乱码编码不一致读的时候指定encodinggbk或utf-8保存时用utf-8-sig明明筛选了却没生效数据没变忘了把返回的新DataFrame赋值回来记住df df[...]或者df df.drop()9.2 两个真正影响代码质量的习惯第一个是“链式操作友好”。pandas里很多操作可以连在一起写不用每步都赋值给新变量。比如df_clean ( df.dropna(subset[金额]) .assign(月份pd.to_datetime(df[日期]).dt.month) .groupby(月份)[金额] .sum() .reset_index() )这种写法看着高级其实底层逻辑和你拆开写是一样的。它有个好处是逻辑清晰中间不会产生多余的临时变量。但缺点是你不能在中间步骤里打印验证结果。我的建议是调试阶段拆开写逻辑确认无误后可以合并成管道式写法让代码更简洁。第二个是“复制视图和修改原数据的分寸”。pandas里有copy()方法但很多人用不好。比如筛选出来的子DataFrame你改了里面的某个值有时候会带着把原DataFrame的对应值也改了这是视图和副本机制导致的。避免这个问题的稳妥办法是只要你对筛选出来的数据要做修改操作先.copy()一份df_sub df[df[城市] 北京].copy() df_sub.loc[0, 销售额] 999 # 这样才不影响原df如果你不做copy直接用变量去修改翻车只是时间问题。我一个前同事就因为这个机制吃过闷亏他改了筛选出来的子表结果原表也被改了数据源头直接污染排查了很久才发现问题。从那以后我凡是修改操作都先copy再也不在这个坑上了。10. 写在最后pandas学习的路线建议看到这里你已经把pandas的核心主干知识全部过了一遍。从安装环境到DataFrame和Series从读取数据到数据体检从筛选索引到缺失值处理从groupby聚合到合并输出这些就是在真实项目中最高频使用的操作组合。你说它们简单也好琐碎也好但就是这些基础操作日复一日地组成了数据分析工作的大部分内容。我个人学习pandas时的一个体会是学它的最佳方式不是从头到尾完整读一本教程而是带着一个具体问题去查、去用、去踩坑。你可以找一个自己感兴趣的数据集比如从网站上下载一份公开的食材价格数据、股票历史数据或者体育比赛数据然后试着用它回答几个问题“价格最高的十种食材分别是哪些”、“近五年某只股票的月线走势如何”、“主客场比赛的平均分差有多大”……每解决一个问题你的pandas水平就会扎实一圈。遇到不会的操作就查pandas官方文档或者直接搜索在实践中构成的记忆远比死记函数API牢固得多。我自己这些年用pandas做数据分析项目总体的经验就是基础函数就那么几十个真正重要的不是背函数而是建立起“拿到数据之后先做什么、再做什么”的流程感。数据体检、清洗、筛选、聚合、输出这一套流程走熟了任何领域的数据处理工作你都能快速上手。希望这篇内容对你有实实在在的帮助。如果你在练习过程中遇到了让人崩溃的报错不妨回头看看这篇教程里的避坑清单——很可能你踩的坑我早就踩过了。
返回列表