十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

Pandas数据分析实战:从数据清洗到可视化全流程

Pandas数据分析实战:从数据清洗到可视化全流程 1. 先从一套完整的数据分析流程说起很多人一提数据分析第一反应就是跑模型、画炫酷图表但真实项目里根本不是这么回事。我自己接手过的数据分析工作从拿到数据到最后给出结论百分之七八十的时间都耗在数据清洗上真正用来算指标、画图的时间反而不多。数据是脏的格式是乱的字段是缺的这些才是常态。所以这次的题目我特别认可用Pandas做数据分析核心不在Pandas本身而在于怎么把“清洗”和“可视化”这两头做好。用Pandas做数据分析解决的是这么一串问题数据拿到手之后怎么读进来、怎么检查、怎么补缺、怎么去重、怎么统一格式、怎么做转换然后再去做分组、聚合、关联这些分析操作最后把结果用图表表达清楚。这套流程里Pandas是当之无愧的主力工具。它比Excel强在自动化、可复现又比Spark这类分布式框架轻量太多尤其适合百万行以下的数据。日常业务分析、竞赛特征工程、数据核查、报表自动化Pandas基本都是起步标配。这篇文章适合三类人刚学Python想找实战场景的工作中天天跟Excel打交道想提效的以及已经会用Pandas但总觉得清洗环节不够系统的。我会按一条完整的数据分析流水线来讲从环境安装、Series/DataFrame基础到数据清洗的各种手法再到分组聚合和可视化最后附上我踩过的坑和排查技巧。这条链路你走通一遍以后拿到什么脏数据都不慌了。2. 环境准备装好Pandas搭好地基2.1 安装Pandas的几种方式Pandas的安装本身不复杂但很多人卡在第一步。如果你用的是Anaconda那它已经预装了Pandas直接在Jupyter Notebook里import pandas as pd就行。如果你和我一样习惯用PyCharm或者用的原生Python环境那就需要手动装一下。最常用的方式就是pip安装打开命令行工具输入pip install pandas如果你在PyCharm里也可以通过settings进入Project Interpreter点加号搜索pandas然后安装。这个操作在PyCharm里叫安装包很多初学者第一次装都会在这里迷路其实本质就是图形化的pip命令。我个人的建议是直接学命令行安装因为你以后要装的包会越来越多图形界面点来点去效率太低。国内网络环境下pip直接装速度可能很慢建议用清华镜像源pip install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple装完之后验证一下版本import pandas as pd print(pd.__version__)能看到版本号就说明装好了。这里有个小经验Pandas版本别追新我一般建议用稳定版。有些刚发布的大版本可能带有一些小bug而且第三方教程大多基于比较成熟的版本写的版本差太多会导致很多API对不上平白给自己添堵。2.2 创建Series和DataFrame的练习Pandas的两个核心数据结构是Series和DataFrame。Series是一维数据你可以把它想象成Excel里的一列DataFrame是二维表结构就是你看到的Excel表格本身。理解了这个对应关系很多概念就好懂了。最基础的创建方式要先练熟import pandas as pd # 从列表创建Series s pd.Series([85, 92, 78, 90]) print(s) # 从字典创建Series键变索引 s2 pd.Series({语文: 85, 数学: 92, 英语: 78}) print(s2) # 从字典列表创建DataFrame data [ {姓名: 张三, 科目: 语文, 成绩: 85}, {姓名: 张三, 科目: 数学, 成绩: 92}, {姓名: 李四, 科目: 语文, 成绩: 78} ] df pd.DataFrame(data) print(df)这种练习非常值得做因为实际工作中你遇到的数据多数长这样一行是一条记录列是不同字段。你掌握了从Python原生结构创建DataFrame后面从文件读进来后处理起来思路就是通的。拿到一个DataFrame后我建议第一件事就是跑df.info()和df.describe()一个看数据类型和缺失情况一个看数值分布这两板斧能帮你快速了解数据的整体面貌。2.3 数据类型转换你真不一定玩明白了数据清洗里最常见的一个操作就是类型转换。Python是动态语言Pandas也很宽容但你如果不在合适的时候做类型转换后面分析的结果会非常诡异。举几个我实际遇到过的场景商品价格列读进来是字符串类型比如19.90需要转成浮点数才能做求和、平均。订单时间列读进来是字符串需要转成datetime类型才能做按周、按月统计。ID列被读成了数值类型前面补零被吃掉需要转成字符串。类型转换的核心就是astype方法df[价格] df[价格].astype(float) df[订单日期] pd.to_datetime(df[订单日期]) df[用户ID] df[用户ID].astype(str)转换的时候有两类问题特别容易踩坑。第一类是格式不干净比如价格列里混入了19.90元这种带单位的字符串直接astype(float)会报错。解决思路是先做字符串清洗把非数字字符去掉再转换。第二类是数据量大的时候astype之后就报内存不足或者等待时间过长这时候可以考虑使用更节省内存的类型比如把int64转成int32或者用category类型处理重复值很高的字符串列。我遇到过客户并行跑任务内存爆掉的情况排查下来就是字符串列没用category类型。3. 数据清洗实战把脏数据洗成能用的干净表3.1 数据加载与初步体检数据清洗的第一步是把数据读进来并做全面的体检。Pandas读取文件的接口很多最常用的是read_csv和read_excel。业务上常见的肮脏数据无非几类缺失值、重复值、异常值、格式混乱。我们要用到的就是清洗的每一个步骤。我先从一个比较有代表性的例子说起——一张订单表包含订单编号、用户ID、商品名称、价格、数量、下单时间这几个字段。实际拿到的数据往往会有各种问题。读文件的时候有个技巧很多人不知道可以顺手做几件事df pd.read_csv( order.csv, encodingutf-8, # 如果报错试试gbk dtype{用户ID: str}, # 指定列类型 parse_dates[下单时间] # 自动解析时间列 )读取之后用几个基础方法做体检df.shape # 行数和列数 df.head() # 前几行 df.info() # 字段类型、非空值统计 df.describe() # 数值分布 df.isnull().sum() # 每列缺失值个数 df.duplicated().sum() # 重复行数shape告诉你数据规模是几行几列info告诉你每列有没有缺失、类型是什么describe帮你看到数值列的均值、最值和分位数。这些信息拼在一起你对数据的基本盘就心里有数了。我一般习惯把这几个命令的输出全部过一遍再开始动手直接看着数据就动手容易漏掉隐藏问题。3.2 缺失值处理先判断再动手缺失值是最常见的脏数据处理的核心原则是“先判断缺失的含义再决定处理方式”不要一上来就dropna()全删掉。举个例子某个订单表里面的优惠券金额列缺了很多值。你需要判断这个缺是因为没使用优惠券所以为空还是数据采集时丢了。如果是前者填充0是完全合理的如果是后者填充均值都未必靠谱更稳妥的方式可能是删除或用模型估计。判断清楚之后常见的处理方式有这么几种# 删除有缺失值的行 df.dropna(inplaceTrue) # 填充固定值 df[优惠券金额].fillna(0, inplaceTrue) # 填充统计值均值/中位数 df[评分].fillna(df[评分].mean(), inplaceTrue) # 向前填充或向后填充适用于时间序列 df[成交量].fillna(methodffill, inplaceTrue) df[成交量].fillna(methodbfill, inplaceTrue)这里我特别想强调一点inplaceTrue这个参数意味着直接修改原DataFrame。老版本Pandas支持得好但新版本里很多方法已经开始提示推荐使用df df.fillna(...)这种写法了。我自己的习惯是能不inplace就不inplace尽量返回新对象这样链路清晰、好调试也不会因为误操作把原始数据破坏掉。做数据分析要有这个洁癖原始数据永远只读清洗过程写在新表里这样后面发现洗错了还能回溯。3.3 重复值与异常值该删就删该查就查重复值判断最常用的是duplicated()和drop_duplicates()。这里有个细节判断重复不一定整行完全一样才算重复。比如订单表用户ID和订单日期相同就已经很可疑了。所以我有几个字段就按这几个字段来判断重复df.drop_duplicates(subset[用户ID, 下单时间], keepfirst, inplaceTrue)keep参数可以控制保留哪一条保留第一条、最后一条或者全部不保留都行看你的业务逻辑决定。异常值处理比重复值要需要业务思维。一个订单的金额是-20元肯定是异常一个用户单日下单1000次可能是刷单也可能就是异常。处理异常值的基本思路是先通过describe()看数值分布再用条件筛选把这些极端值挑出来人工判断df[df[价格] 0] # 找负数 df[df[价格] df[价格].quantile(0.99)] # 找顶部1%极值筛选出来之后是删除、替换为临界值还是单独标记需要结合业务场景判断。我的经验是异常值先别急着删把它们单独存一份文件留档这样你最终报告里可以写清楚“清洗了多少行、为什么清洗”逻辑完整而且方便汇报。3.4 字段格式统一与时间数据处理格式统一这件事在真实数据里几乎每次都要做。最常见的就是日期数据和时间抓取。用户上传的Excel里的时间列能看到的格式五花八门2023-01-15、2023/1/15、20230115、15-01-2023。Pandas自带to_datetime能解析绝大部分常见格式df[下单时间] pd.to_datetime(df[下单时间])转完之后你就可以顺手做一堆时间上的衍生字段这些字段后续分析特别有用df[下单日期] df[下单时间].dt.date df[下单月份] df[下单时间].dt.month df[下单小时] df[下单时间].dt.hour df[周几] df[下单时间].dt.dayofweek字符串格式的清洗我用得最多的是str.strip()、str.replace()和str.extract()。比如商品名称带前后空格、全角半角混用价格带¥符号这些都需要清洗。Pandas里有个很好用的思路你可以在apply函数里面传入自定义的清洗逻辑def clean_price(value): if isinstance(value, str): value value.replace(¥, ).strip() return float(value) return value df[价格] df[价格].apply(clean_price)这个函数你可以无限扩展这就是清洗规则。数据清洗规则梳理成一份文档非常必要。我自己的清洗规则一般是一份Markdown表格每列什么类型、缺失怎么处理、重复怎么判断、异常怎么标记、格式怎么统一。洗数据洗到最后这项规则比清洗代码本身还值钱因为团队其他成员可以照着规则理解你的整个流程。4. 数据分析核心操作分组、透视与关联4.1 groupby分组聚合数据分析的基本功数据洗得差不多了接下来才是真正“算指标”的阶段。Pandas的分组聚合用groupby学这个的时候我一直强调一句话先分组、再聚合脑子里想着“按某某字段分组算每组什么指标”。以订单数据为例常见需求是不同商品类别的总销售额、每个用户的下单次数、每个月的订单总量。写法非常直观# 不同商品类别的销售额 df.groupby(商品类别)[销售额].sum() # 每个用户的下单次数 df.groupby(用户ID)[订单编号].count() # 每个月的订单总量 df.groupby(下单月份)[订单编号].count()groupby之后你选的那个字段比如销售额会被映射到对应列上再用sum、mean、count、max、min这些聚合函数算结果。如果你要一次算多个指标用aggdf.groupby(商品类别).agg({ 销售额: [sum, mean, count], 数量: sum })这里有个容易混淆的点count()和sum()的区别。count()统计的是非空值的个数sum()做的是数值求和。比如你想看“某个用户总共下单几笔”那用count()数订单编号的非空个数想看“这个用户花了多少钱”就用sum()对销售额求和。别把这两个用混了那是致命的。4.2 pivot_table透视表Excel透视表的Python版用过Excel透视表的同学上手pivot_table会非常快。它的作用就是把一张长表一行一条明细记录变成宽表行是某个维度、列是另一个维度、值是汇总指标。场景举例我想看每个月份、每种商品类别的销售额情况。用透视表一句话搞定pivot df.pivot_table( index下单月份, columns商品类别, values销售额, aggfuncsum, fill_value0 )行是月份列是商品类别值是销售额缺失的组合自动填0。这样一个交叉表拿去做热力图或者直接截图放到报告里都很直观。pivot_table的可选参数不少但核心就是上面这四个index、columns、values、aggfunc。aggfunc我最常用的是sum、mean和count取决于你要算总量、平均值还是次数。4.3 merge做表关联多张表拼成一张大表真实业务场景里数据很少整整齐齐全部在一张表里。往往是订单表、用户表、商品表各自独立需要做关联才能获得完整信息。Pandas的merge就是干这个的用法跟SQL里的JOIN是一个道理。# 订单表关联用户表取用户所在城市 order_user pd.merge( df_order, df_user, on用户ID, howleft )on指定关联字段how指定关联方式。left表示以左表为主匹配不到的右表字段就是NaN。日常做业务分析大部分情况用left就够了因为你不想丢掉主表里的任何一条记录。inner只会保留两边都匹配得上的适合做交集筛选。做完merge之后我建议每次都检查一下行数有没有变多因为如果两表之间有重复的关联键会让结果翻倍膨胀。这个错误很隐蔽我在一次销售数据分析时就因为这个把销量算高了好几倍后来发现是用户表里有重复的用户ID。检查方法很简单merge之后对比一下行数是否等于左表行数如果多了多半就是关联键有重复。5. 可视化呈现让数据自己说话5.1 中文显示与绘图环境配置Pandas本身不带绘图功能它是借助matplotlib在背后完成绘图的。所以你需要先确保matplotlib已经安装然后用一行魔法让它和Pandas衔接好import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] # 解决中文乱码 plt.rcParams[axes.unicode_minus] False # 解决负号显示问题SimHei是黑体Windows系统一般预装Linux服务器上如果没有对应字体就需要安装中文字体再指定。负号问题经常被人忽略默认字体下负号会变成一个方块设置unicode_minus为False就行。这两行配置是所有中文图表的前提每次建新的Notebook我都会先写下这两行。5.2 常见图表怎么选别乱画Pandas里直接调用plot()方法就行但图表类型选择是有讲究的不是所有图都适合所有数据。柱状图适合对比各类别的大小比如各商品类别的销售额对比。折线图适合看趋势比如每月的订单量变化。饼图适合看占比比如渠道来源占比但分类超过五个就不建议了。箱线图适合看分布比如各品类价格的波动范围。散点图适合看两个数值变量之间的关系比如价格和销量的相关性。我最常用的是前面两种。举个例子把不同月份的销售额画出来monthly_sales df.groupby(下单月份)[销售额].sum() monthly_sales.plot(kindline, markero, figsize(10, 5)) plt.title(月度销售额趋势) plt.xlabel(月份) plt.ylabel(销售额) plt.grid(True) plt.show()kind参数控制图表类型figsize控制尺寸markero给折线加个圆点标记让数据点更清楚。画完之后plt.title、plt.xlabel、plt.ylabel这些都要写全不然拿到汇报里去别人看不懂坐标轴是什么意思。我见过太多图连轴标签都不写别人根本没法看。5.3 多图组合与报告输出实际做数据分析怎么可能只要一张图。你需要把几个相关图表拼到同一个画布上用subplots就可以实现。我习惯用一行代码创建多个子图fig, axes plt.subplots(2, 2, figsize(14, 10)) df.groupby(商品类别)[销售额].sum().plot(kindbar, axaxes[0][0], title各类别销售额) df.groupby(下单月份)[销售额].sum().plot(kindline, axaxes[0][1], title月度销售趋势) df.groupby(商品类别)[销售额].mean().plot(kindpie, axaxes[1][0], title平均客单价占比) df.plot(kindscatter, x价格, y数量, axaxes[1][1], title价格与数量关系) plt.tight_layout() plt.show()subplots(2, 2)除以生成两行两列的布局每个子图通过ax参数指定位置。tight_layout()会自动调整子图间距避免标题和标签互相挤到。这套组合拳打下来一张总览图面就出来了直接可以贴到汇报PPT里。如果你要做那种大屏展示或者更复杂的可视化项目Pandas这边输出的通常是把分析结果导出成干净的Excel或CSVresult.to_excel(销售分析结果.xlsx, indexFalse)然后交给FineReport、DataV这类可视化平台去呈现。Pandas的定位是把数据算得清清楚楚可视化交给专业工具这个分工我觉得是最舒服的。6. 常见报错与排查技巧实录6.1 AttributeError: module pandas has no attribute core这个报错我遇到过一次当时差点崩溃。整个pandas包好像废了一样很多方法都调不出来。后来一查发现原因是项目目录下有一个文件名字叫pandas.py它把真正的Pandas模块遮蔽了。Python导包时会先在当前目录找找到同名文件就直接加载了那个假的。解决方案很简单把命名冲突的文件重命名掉然后重启一下解释器。这个坑提醒我两件事第一永远不要用pandas.py、numpy.py这些和库名一样的名字命名自己的脚本第二出现奇怪的报错时先看看当前目录下有没有同名文件。6.2 文件读取编码报错read_csv的时候最常见的报错是编码问题提示UnicodeDecodeError。通常解决方法是换个编码参数df pd.read_csv(data.csv, encodinggbk)Python默认的编码是UTF-8但国内很多系统导出的CSV默认用的是GBK。我的习惯是先用encodingutf-8试一次报错就换encodinggbk有时候还需要用encodinggb18030它是GBK的超集兼容性更好。打开文件前先丢到Notepad或VS Code里看一眼右下角编码就不会反复试了。6.3 字段类型导致的隐性问题这个问题最坑人因为它不报错但结果就是错的。比如一个订单ID列在Excel里显示是19位数字读进Pandas后变成了浮点数后面你再拿去关联用户表怎么都对不上。为什么对不上因为浮点数精度有限长数字被四舍五入了。解决方法是读取时直接指定列类型df pd.read_csv(order.csv, dtype{订单ID: str})这是一条非常重要的实操经验像ID、手机号、银行卡号这类看着像数字但本质是文本的字段读取时一定要指定为字符串类型否则精度丢失问题会让你排查到怀疑人生。6.4 数据清洗规则速查表最后整理一份我实操中沉淀下来的清洗规则照着做大概率能避开大多数坑数据类型常见问题处理方式参考代码ID类字段被读成数值、精度丢失读取时指定dtype为strdtype{订单ID: str}日期时间格式混乱、类型是字符串用to_datetime统一解析pd.to_datetime(df[时间])数值字段带货币符号、千分位、前后空格字符串替换astype转换df[金额].str.replace(,, ).astype(float)文本字段前后空格、大小写不统一str.strip() str.lower()df[城市].str.strip().str.lower()缺失值NaN影响后续计算先判断含义再填充或删除df.fillna(0)/df.dropna()重复值整行或指定列重复drop_duplicates按子集去重df.drop_duplicates(subset[用户ID])异常值负价格、超大数据分位数筛选单独留档df[df[价格] 0]排查问题的时候按表格顺序逐列检查一遍绝大多数脏数据问题都能定位。我做数据分析这些年最大的体会就是Pandas的API不难学难点全在于你有没有一套系统化的清洗思路。一个人遇到缺失值就dropna()、遇到异常值就删行跟一个按规则排查、按字段处理的分析师做出来的报告质量是完全不一样的。最后再分享一个我个人的习惯。每次完成一套数据分析我都会把整个处理过程整理成一个带注释的脚本存下来文件名写清楚项目和日期。下次再遇到结构类似的数据直接照着脚本改改字段名就能复用。这种积累会随着项目越来越多越来越值钱某种意义上它就是你的数据清洗方法论。用Pandas做数据分析真正拉开差距的从来不是谁代码写得花哨而是谁在面对混乱数据时更有章法。
返回列表