零基础学Python数据分析:数据清洗、分组聚合与可视化实战 1. 零基础学数据分析到底在学什么先别急着背语法我一直觉得“Python零基础14数据分析”这个标题放在系列的第14篇其实是恰到好处的。前面十几篇如果已经让你把Python的基本语法、列表字典、循环判断这些东西混了个脸熟那么到数据分析这一篇你就不是“从零开始”而是“从语法开始走向应用”。但如果你真是从头直接跳到这里来看也没关系我会把所有用到的基础语法都解释到“能抄作业”的程度。先说清楚一个最容易被误解的事数据分析不是数学竞赛。你不需要先学完概率论、线性代数才能动手实际工作中大量的分析任务说白了就是四件事——把数据读进来、把脏数据洗干净、把数据分组汇总、再把结果画成图讲给别人听。这四件事Python生态里都有现成的工具尤其是pandas和matplotlib这两个库它们就是为“零基础也能上手干活”设计的。那这篇博文到底要解决什么问题我用一句话概括给一个只有Python基础语法、完全没接触过数据分析库的人一条能最快跑通“导入数据—清洗—统计—出图—得出结论”全流程的路线图。你跟着做下来不会成为数据分析专家但你会拥有一套可以套用到很多真实场景的完整套路以后再看见Excel表、CSV文件、后台导出的数据你不会再发怵而是知道从哪里下手。另外要补充一句这篇内容里面我会用到两个核心库pandas和matplotlib。如果你还没安装不用慌后面我会单独讲安装和验证把这个零基础最容易卡住的环节也一并理顺。2. 第一步不是写代码是把“数据原料”准备好2.1 选一个够真实又够简单的数据集我见过太多零基础的人倒在“选数据”这一步。有人一上来就去爬网站、找那种几十万行的真实业务数据结果数据里面的坑比收获还多光清洗就洗了两天最后得出结论“数据分析太难了我不适合”。我的建议是第一次练手数据集要满足三个条件——体量小、字段少、贴近生活。体量小是指几百行就够甚至几十行也能跑通流程字段少是指列名一眼能看懂比如日期、商品名、销售额、数量而不是一堆英文缩写贴近生活是指你看到数据就知道它大概在讲什么这样即使分析结果有点奇怪你也能凭常识判断是不是哪里做错了。我常用的练手数据是某公司的模拟销售记录格式大致长这样日期,商品类别,商品名称,销售量,单价,销售金额,销售区域,销售人员 2025-01-03,数码,无线耳机,12,299,3588,华东,张三 2025-01-05,食品,坚果礼盒,45,88,3960,华南,李四这种表格就是一个典型的“宽表”每一行是一条销售记录每一列是一个维度的信息。你不需要去网上下载什么复杂数据自己在记事本里敲几十行这样的记录或者从Excel里导出一个CSV文件就完全可以作为入门数据。CSV逗号分隔值文件是数据分析里最常见的数据格式Excel可以直接另存为CSV后面我们所有代码示例都基于这种文件。2.2 环境选择Jupyter Notebook比纯脚本更适合入门我强烈建议零基础阶段用Jupyter Notebook而不是直接在纯Python文件里写代码。原因很简单数据分析是一个“试错”的过程你经常要读一行数据、看一个结果、再决定下一步干什么。Notebook的“单元格”模式让你可以把代码分成小块一块一块地执行每一个中间结果都看得见这对培养直觉非常有帮助。安装这一步也顺便说清楚。如果你之前已经装好了Python那么直接在命令行运行pip install pandas matplotlib如果你想一次性把环境都搞定也可以直接安装Anaconda它会自带pandas、matplotlib、Jupyter Notebook这些工具省去很多依赖问题的折腾。装完之后在命令行输入jupyter notebook浏览器里会打开一个界面新建一个Python 3的笔记本就可以开始了。注意我在实际带人入门的时候发现最常遇到的问题不是库装不上而是“装到了不同的Python环境里”。如果你电脑上装过多个Python版本建议在命令行里用pip --version确认一下当前pip属于哪个Python再用python -c import pandas; print(pandas.__version__)验证导入是否成功。这个步骤虽然不起眼但能省掉后面一大半的“ModuleNotFoundError”。2.3 用pandas读入数据后先别急着做分析拿到CSV文件之后读入只需要一行代码import pandas as pd df pd.read_csv(sales_data.csv, encodingutf-8)读进来之后我建议你第一件事不是算总额也不是画图而是“打量”这份数据。用什么打量三招就够了df.head()看前几行长什么样df.info()看每一列的数据类型和缺失值情况df.describe()看数值列的统计概况。这三行代码跑完你对整个数据的基本盘就有数了。这里有一个零基础容易忽略的点read_csv里的encoding参数。如果文件里有中文经常会出现乱码常见的原因就是编码不匹配。UTF-8读取不了的时候可以试试encodinggbk尤其是从Windows上的Excel导出的CSV文件大概率要用GBK。这一行参数虽然小但第一次遇到乱码时能救命。3. 让数据“听话”清洗与整理是真正见功底的地方3.1 先做类型检查和转换别让pandas“猜错”很多人以为数据分析最难的环节是建模、是算法但实际上真正占据一个数据分析师日常时间最多的工作是数据清洗。有一句话我特别认同数据分析里80%的时间都花在清洗数据上20%的时间用来分析但大家记住的都是那20%的成果。初次接触清洗你不需要掌握所有方法只需要先关注三类最常见的问题类型不对、缺失值、重复值。先看类型不对。比如“销售金额”这一列在Excel里看起来是数字但导入pandas后很有可能是对象object类型也就是字符串。原因通常有两个数据里有“”这种千分位分隔符或者有些单元格里混进了空格、异常字符。要检查类型用df.dtypes要转换用pd.to_numeric它会自动尝试把字符串转成数字。df[销售金额] pd.to_numeric(df[销售金额], errorscoerce)这里的errorscoerce意思是转不过来的值变成NaN缺失值而不是报错中断。很多教程不会专门强调这个参数但实际数据里几乎一定会有脏数据加了这句就不会因为一行坏数据让整个程序崩溃。这就是“以防万一”和“硬碰硬”的区别。3.2 缺失值处理先弄清楚“为什么缺”再决定“怎么处理”缺失值在pandas里显示为NaN它不是0也不是空字符串而是一个“这里没有值”的标记。很多零基础的人看到NaN就条件反射地删除这其实是偷懒的做法。我在实际项目里踩过坑之后才明白处理缺失值之前一定要先问自己这行数据为什么缺是数据源本身没记录还是清洗过程中转类型失败造成的如果只是少数几行缺失而且后续分析用不到这行数据直接删除是可以接受的用df.dropna()。但如果你要做的是统计汇总比如算销售总额那缺失值就会影响结果。这时候更稳妥的做法是用合理的值去填充。什么叫合理要看业务场景。销售金额缺失用整列的平均值填算是一个比较中性的选择df[销售金额] df[销售金额].fillna(df[销售金额].mean())但对于“销售量”这种本身取值应该比较规律的字段用中位数可能比平均数更合理因为中位数不容易被极大极小值拉偏。我教零基础朋友的时候会打一个比方平均数像班里所有同学成绩的“平均水平”但如果有一个同学考了特别高的分平均水平就会被拉高中位数则是“站在中间那个人”的成绩更皮实。在数据有离群值的时候中位数往往更可靠。3.3 增加新字段从日期里拆出“月份”是性价比最高的一步数据清洗不光是修问题也包括“造新数据”。最典型的一个操作是从日期列里提取出年、月、日、星期几之类的信息。为什么这么做因为很多时候单看“2025-03-15”这个完整日期你很难直接看出规律但如果你把它拆出“月份”和“星期几”数据里隐藏的周期规律就会浮现出来。df[日期] pd.to_datetime(df[日期]) df[月份] df[日期].dt.month df[星期几] df[日期].dt.dayofweekpd.to_datetime是把文本日期转成真正的时间类型转完之后.dt后面就可以接很多时间相关的属性了。月份是1到12的数字星期几是0到6的数字周一是0周日是6。这一步做完你的数据表就比原来多了两列“现成的分析维度”后面做按月汇总、按星期汇总都变得非常方便。4. 分组聚合与排序分析思路从“看一眼”变成“算一算”4.1 groupby的底层逻辑一句话说清“拆、算、合”数据分析里最常干的一件事就是“按某个维度汇总数值”。比如按销售区域求总销售额按商品类别求平均销售量按月份求总销售额并找出旺季淡季。这个需求在pandas里用groupby实现看名字就知道它的逻辑是“分组”。我拆解一下df.groupby(销售区域)[销售金额].sum()这行代码到底发生了什么第一步pandas先把整张表按“销售区域”的不同值分成几个小组第二步对每一组的“销售金额”这一列执行求和操作第三步把每个组的结果合并成一张新表。这个思路你不需要背只需在脑子里记住“拆、算、合”三个字。实操中经常是从一个分组维度变成两个分组维度。比如想看“每个区域每个月的销售额”就可以这样写monthly_region df.groupby([销售区域, 月份])[销售金额].sum()这样得到的结果是一个带双层索引的Series有点别扭。如果想让结果更像表格用reset_index()就能把索引变成普通列。再加一个参数as_indexFalse可以让聚合结果直接保持为DataFramemonthly_region df.groupby([销售区域, 月份], as_indexFalse)[销售金额].sum()这里我想多说一句零基础学groupby最容易犯的错误是忘了reset_index或者as_index导致结果是一个“看起来很奇怪”的对象然后就开始怀疑自己写错了。其实不是写错了只是pandas默认把分组的键变成了索引它不是用来直接“看”的而是用来“继续操作”的。遇到这种情况别慌加一行reset_index()就回到你熟悉的表格结构了。4.2 透视表把“分析维度”摊开来看如果你用过Excel的数据透视表那pandas的pivot_table对你来说应该很亲切。它能做跟groupby类似的事情但结果是以“交叉表”的形式呈现行是一个维度列是另一个维度表格中间是汇总值。这种形式的优势是直观适合人脑直接对比。举个例子。我想看每个销售区域在不同商品类别上的总销售额用透视表写pivot pd.pivot_table( df, values销售金额, index销售区域, columns商品类别, aggfuncsum, fill_value0 )这段代码的意思一目了然values指定要对哪一列求和index是行维度columns是列维度aggfunc是汇总方式sum、mean、count都可以fill_value是把没有数据的格子填成0而不是NaN。我建议第一次做透视表时就按这个“四要素”来理解值、行、列、怎么汇总。对比groupby和pivot_table我的经验是如果分析目标是“接下来还要继续用这些数据做各种计算”用groupby更顺手如果目标是“把结果打印出来给人看、让老板一眼看懂对比关系”用pivot_table更直观。两者不是谁替代谁的关系而是不同场景下的两种表达。4.3 排序和Top N分析结果别一锅端聚焦关键对象分组聚合做完你得到的结果往往是一张几十行的汇总表。这个时候如果直接拿全表去讲结论听众根本抓不住重点。比较聪明的做法是排序然后只看前几名。按销售额降序排列然后取前三名用sort_values加headtop3 df.groupby(商品类别, as_indexFalse)[销售金额].sum().sort_values(销售金额, ascendingFalse).head(3)这行代码有点长但它的结构其实很像一条流水线先分组求和再按金额排序最后取前3行。零基础阶段我建议把这种“链式写法”拆成几步来做每步用print看看中间结果熟悉之后再合成一行。head()和tail()是pandas里特别常用的两个“取数”工具分别取前几行和后几行。在探索阶段多用head()看数据能有效防止程序一次性打印几千行把控制台刷爆。5. 画图让分析结论“一眼被人看懂”5.1 matplotlib第一步从折线图开始理解“画布”和“坐标系”数据算完了下一步是把结果可视化。Python生态里画图工具不少但对于零基础matplotlib永远是我的第一推荐。原因有三个它是最基础的绘图库几乎所有其他绘图库都建立在它之上它的概念简单就是“画布坐标系图形元素”它跟pandas的配合很自然。折线图适合展示数据随某个连续变量变化的趋势最典型的就是“月度销售趋势”。先算按月汇总的数据monthly df.groupby(月份, as_indexFalse)[销售金额].sum()然后画图import matplotlib.pyplot as plt plt.figure(figsize(8, 5)) plt.plot(monthly[月份], monthly[销售金额], markero) plt.xlabel(月份) plt.ylabel(销售金额) plt.title(月度销售金额趋势) plt.show()这里面figure(figsize...)是创建画布并设置宽高plot是画线markero是在每个数据点画一个圆点标记方便看清楚每个月的具体位置。xlabel、ylabel、title不言自明。跑完这段如果能看到一张带趋势的折线图恭喜你你已经在“用Python讲故事”了。5.2 柱状图和饼图对比和构成要选对图柱状图适合做“分类对比”比如对比各个区域的销售总额。画法很简单region_sum df.groupby(销售区域, as_indexFalse)[销售金额].sum() plt.figure(figsize(8, 5)) plt.bar(region_sum[销售区域], region_sum[销售金额]) plt.xlabel(销售区域) plt.ylabel(销售金额) plt.title(各区域销售金额对比) plt.show()饼图适合展示“构成比例”也就是“谁占了多少”。但这里我要提醒一句饼图在数据项很多的时候会非常丑而且不同扇区面积相近时很难对比。所以我的建议是饼图最多用来展示3到5个分类的占比超过5个就改用柱状图或者把次要的类别合并成“其他”。这不是什么高深原理纯粹是用图的经验——人的眼睛对“长度”的对比能力强对“面积”和“角度”的对比能力弱得多。5.3 中文乱码新手碰到的第一个“系统性难题”matplotlib默认是不支持中文显示的标题或坐标轴里凡是中文画出来全是方块。这是零基础阶段最让人崩溃的问题之一但解决方法其实非常简单在你的绘图代码前加上三行plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False第一行指定了中文字体SimHei黑体是Windows系统自带的第二行是为了让负号正常显示。如果你用的是Mac系统可以把SimHei换成Arial Unicode MS或PingFang SC。我建议把这套配置固定写到一个单独的单元格里每次开始分析前先跑一次相当于“全局设置”。还有一个细节容易被忽略rcParams设置要在绘图之前执行。很多人把设置的代码贴在plt.show()之后发现没生效就开始折腾其他东西最后折腾好久才发现是顺序问题。先设置后绘图这个顺序记住了能少一次白熬夜。6. 一个完整小案例从零开始跑通“数据到结论”6.1 案例目标找出哪个月卖了多少钱、哪类商品贡献最大、哪个区域需要关注前面讲了一堆工具现在把它们拼起来走一遍流程。我假设你已经准备好一份模拟的销售数据CSV里面包含日期、商品类别、销售金额、销售区域这几个字段。我们这次的目标很简单回答三个问题。第一全年销售趋势如何哪个月是旺季、哪个月是淡季第二哪个商品类别贡献了最多的销售额第三哪个销售区域的表现最需要关注。这三个问题分别对应折线图、柱状图和排序分析正好把前面学的知识点都用上。6.2 完整代码流程读数据、清洗、汇总、画图一气呵成下面我写一个完整流程每一步都带注释。你不需要一次看懂每一行跟着跑一遍再回头逐行理解这个过程中建立的“整体感”比看十段零散代码都更有效。import pandas as pd import matplotlib.pyplot as plt # 1. 设置中文字体 plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False # 2. 读入数据 df pd.read_csv(sales_data.csv, encodingutf-8) # 3. 类型转换与新增月份字段 df[销售金额] pd.to_numeric(df[销售金额], errorscoerce) df[日期] pd.to_datetime(df[日期]) df[月份] df[日期].dt.month # 4. 去除销售金额缺失的记录 df df.dropna(subset[销售金额]) # 5. 月度汇总 monthly df.groupby(月份, as_indexFalse)[销售金额].sum() # 6. 月度趋势图 plt.figure(figsize(8, 5)) plt.plot(monthly[月份], monthly[销售金额], markero) plt.xlabel(月份) plt.ylabel(销售金额) plt.title(月度销售金额趋势) plt.show() # 7. 商品类别汇总排序 category_sum df.groupby(商品类别, as_indexFalse)[销售金额].sum() category_sum category_sum.sort_values(销售金额, ascendingFalse) # 8. 类别对比柱状图 plt.figure(figsize(8, 5)) plt.bar(category_sum[商品类别], category_sum[销售金额]) plt.xlabel(商品类别) plt.ylabel(销售金额) plt.title(各商品类别销售金额) plt.show() # 9. 找到月度销售额最低的区域 region_monthly df.groupby([销售区域, 月份], as_indexFalse)[销售金额].sum() worst_region_month region_monthly.sort_values(销售金额).head(1) print(worst_region_month)这段代码跑完你会得到一张趋势图、一张对比图、一个输出结果。虽然只是基础操作但你已经完成了一轮完整的“数据探索式分析”。6.3 把结果写成一句“人话”分析做完最后一步不是展示代码而是把结果讲清楚。这一步往往是很多零基础教程会漏掉的关键。我自己的习惯是每次分析收尾时强制自己用一句话写下结论。比如看完上面代码跑出来的结果你可以这样总结下半年整体销售趋势上升12月是全年峰值可能是年末促销影响数码类是销售额最大品类占比约40%某区域在某个月的销售额明显偏低建议核查该区域的促销排期或人员配置。这段话没有写任何代码但它是整个分析的最终产出因为数据只有被翻译成业务结论才真正产生价值。7. 常见问题速查那些教程没写但一定会遇到的坑7.1 报错“ModuleNotFoundError: No module named pandas”说明pandas还没有安装或者当前运行环境不是安装pandas的那个环境。解决方案是回到命令行执行pip install pandas然后确认python -c import pandas不报错。如果之前已经安装但仍然报错检查是否在Jupyter里使用的Python内核与命令行中的Python不一致这是环境问题里最常见的一种。7.2 数据中有中文读进来乱码优先检查文件编码。CSV文件如果带BOM头UTF-8读取时列名会带上奇怪的字符这时候用encodingutf-8-sig可以解决。如果中文内容乱码可以尝试encodinggbk。这个经验我写过无数次了几乎每个零基础项目都会遇到一次。7.3 日期列一直转不成日期类型先打印这一列的独特值看一看。df[日期].unique()能快速列出所有不重复的值如果里面有日期格式不统一的字符串比如有的写“2025/1/1”有的写“2025年1月1日”pd.to_datetime可能无法统一转换。遇到这种情况先用errorscoerce让转不出来的变成缺失值然后针对异常值单独处理。零基础阶段不追求处理得完美追求的是“知道问题出在哪”。7.4 画出来的图没有线条只有一个空坐标系常见的原因是plt.show()在代码块里执行了两次或者前面已经show过一次导致当前画布被清空。另一个常见原因是你在一个函数里画图但没有在函数开头创建新画布导致所有图形画在了同一块画布上。解决办法是每次画图前先plt.figure(figsize(8, 5))相当于“换一张新纸再开始画”。7.5 groupby之后打印结果发现多了一列索引这不是错误是pandas的默认行为。如果你不想看到索引加reset_index()如果你希望以后继续按这个分组的键进行操作保留索引有时候反而更方便。理解索引的概念确实需要一点时间但它是pandas里你最值得花功夫弄懂的概念因为几乎所有的“奇怪现象”都和索引有关。8. 送你一套“数据分析第一周”的练习路径到这里整条流程已经走完了。如果只给你一个建议我会说不要急着学那些复杂的“进阶技巧”先用小数据集把今天这套流程扎实地跑三遍。第一遍我建议你完全照抄代码跑通即可目的是熟悉工具和环节第二遍换一个自己熟悉的数据集哪怕是自己手工输入的“一周零花钱记录”也要逼着自己完成读入、清洗、汇总、画图这四个环节第三遍尝试改一个环节比如把“按月份汇总”改成“按星期几汇总”看看得到的结果能讲出什么新故事。挖掘标题背后的深层价值其实就是希望你能从“看我操作”变成“自己动手”从“跟着代码走”变成“带着问题来试”。数据分析这门技能最大的门槛从来不是语法而是“动手去折腾”的勇气。很多朋友学了语法就看教程看了教程就觉得自己会了但真正关掉参考文档、对着一个空白笔记本发愣时才知道自己哪里没懂。没有关系犯错也是数据的一部分分析自己的“错误日志”也算一次不错的数据分析练习。