
第二次作业这四个字放在课程目录里平平无奇放在我的学习记录里却是一道实打实的分水岭。第一周交上去的第一次作业代码能跑图表能出结论勉强写了一段但老师批注里只留了一句话讲清楚你的思路。所以在做第二次作业的时候我给自己定的目标很简单不止要把结果做出来还要让每一步都经得起追问。这次作业是一份数据分析与可视化任务课程提供了一张脱敏后的电商订单表大约十万行要求完成数据清洗、销售维度分析和可视化报告最终提交一份可复现的分析文档。如果你也正在为课程作业、实训项目或者自学练手发愁尤其是那种“数据给你了剩下的全靠自己折腾”的作业这篇内容应该能给你一些参考。我不打算只贴最后的成品效果而是把整个从零到一的过程拆开讲包括我踩过的坑、反复修改的图表、以及最后让我拿高分的几个关键习惯。这些经验放之四海皆准换一个数据集、换一门课思路完全能复用。1. 第一次作业到第二次作业差的是习惯1.1 第一次作业暴露了什么我的第一次作业其实做完得很早但问题同样很明显。代码全部堆在同一个单元格里从上到下几十行中间没有任何注释读起来跟天书一样。当时自己跑通了还觉得挺顺利结果老师一打开就露馅了文件路径写的是本地绝对路径换一台电脑根本跑不了图表用的是默认样式中文字体还变成了方框。这些细节放在代码能跑的层面看确实不影响结果。但如果把一道作业当成一个小项目来看它就是不及格的。第一次作业告诉我最重要的一件事过程的组织能力和结果的正确性同样重要。一个能跑通但思路混乱的notebook和一个逻辑清晰的notebook差的不是代码量而是背后对问题的梳理程度。所以第二次作业我在动手之前先做了一遍完整的复盘把第一次作业里不合理的地方列成了一个清单逐项规避。1.2 第二次作业的评价标准不一样了第二次作业给我的感受是评价维度从“功能是否完整”升级到了“逻辑是否成立”。也就是你的结论必须经得起数据和图表的支撑而不是拍脑袋写出来的总结。老师没有明说评分标准但从作业要求和批注风格能看出来他更关注的是这几点。数据清洗是否考虑了业务场景而不是无脑删除或填空。分析维度是否覆盖了多个角度而不是只挑好看的数据讲。图表是否有标题、有标签、有结论注解能不能独立表达信息。报告的每一段结论在图表和数据里是否找得到对应证据。说实话这套标准和公司里做数据分析报告的思路几乎一模一样。第二节课就遇到了这种要求对我来说是好事因为越早养成这样的习惯后面做任何数据相关的事情都会省力很多。1.3 把作业拆成三层的通用方法在正式开始写代码之前我先把“第二次作业”拆成了三个层次数据层、分析层、表达层。数据层读取数据、检查字段、清洗缺失值、处理异常值、统一数据类型。分析层确定分析维度比如时间趋势、地区分布、商品类目对比然后分组统计。表达层选合适的图表、写结论、组织整个notebook的叙述顺序。我当时给自己画了一张时间分配表数据层占四成时间分析层占三成表达层占三成。最后执行下来数据层实际花了接近五成时间因为脏数据的形态永远超出预期这里想提醒各位如果你觉得清洗数据比想象中慢说明你是真的在处理数据不是走过场。这个时间比例一点都不亏数据这一步做扎实了后面分析和画图都会特别顺。2. 这次作业的选题与技术方案2.1 作业题目与需求拆解这次“第二次作业”的完整题目是对一份脱敏电商订单数据进行预处理然后从时间、地区、商品类目三个维度完成销售分析每个维度至少输出两张可视化图表最后写一份不少于八百字的分析报告报告要求有具体的数字和图表作为支撑。拿到题目我先做了一件事把需求拆成“显性要求”和“隐性考核点”。显性要求就是题目里写明白的比如三个维度、两张图表、八百字报告。隐性考核点是我自己推出来的包括数据清洗是否到位、维度拆解是否合理、图表选型是否准确、结论是否有数据支持。把这套拆解做完之后我对作业的难度和方向就有了比较清楚的把握。这个步骤看起来简单但很多人会跳过直接开始读数据。结果往往是做到一半发现某个维度分析不了或者清洗完数据才发现缺失值比例高到影响整体结论只能回头重来。所以我的习惯是先花二十分钟读懂需求再花十分钟规划路径最后才打开代码编辑器。投入产出比极高。2.2 为什么选 Python Pandas Matplotlib技术选型没有悬念课程指定的语言是Python数据处理用Pandas可视化用Matplotlib加Seaborn整个作业在Jupyter Notebook里完成。作业本身不限制工具我也考虑过Excel和Tableau但最后还是用回了Python说几个理由。Excel处理十万行数据不是不行但肉眼检查太累每一个清洗步骤也难以清晰记录。Tableau做可视化确实好看但作业要求“可复现”交一个twbx文件和交一份完整notebook给老师的印象完全不同。Python这套组合最大的优势是全程代码化每一步操作都有记录换一台电脑可以原样复现。还有一个被很多人忽略的好处notebook里可以穿插Markdown单元格把每一段代码的“为什么这么做”写清楚。这正好呼应了老师那句“讲清楚你的思路”。数据清洗的代码本身只是几行但你在旁边写一句“删除订单金额为空的记录因为这些记录占比不到1%且无法从其他字段推断”整份作业的质感立刻就不一样了。2.3 环境准备与数据概况环境的准备比较省事直接装了AnacondaPython版本是3.11Pandas版本是2.0以上。为了避免中文显示问题和其他坑我在notebook第一行就配置了中文字体和负号显示这个细节我后面在常见问题部分还会详细说。数据文件是课程提供的orders.csv一共十万行字段包括订单编号、用户编号、下单日期、收货城市、商品类目、订单金额、支付方式还有一个订单状态字段。拿到文件以后我的习惯是先做三件小事看一眼文件大小、看字段名和类型、看前五行长什么样。这三件事加起来不到一分钟但对后续的理解很有帮助。3. 数据清洗与处理的实操过程3.1 字段体检与缺失值判断打开数据之后我用df.info()和df.isnull().sum()做了第一轮体检情况如下表所示。字段名数据类型缺失数量缺失占比处理方案order_idobject00%无需处理user_idobject00%无需处理order_dateobject00%转为datetimecityobject12031.2%用“未知”填充categoryobject3不到0.01%删除对应记录amountfloat6400%检查异常值pay_typeobject00%无需处理statusobject00%检查取值分布缺失值处理的核心原则是先看比例再定方案。category字段缺失只有三条记录占总体比例可以忽略不计直接删除这三行没有任何影响。city字段缺失占比1.2%如果直接删掉城市维度的分析会少一千多条数据占分析样本的比例不可忽视所以用“未知”单独标记既不丢样本也不影响其他城市的统计。这类决策看起来很小但恰恰是数据分析师日常工作里最常遇到的判断场景。3.2 重复值、类型转换与异常值处理接下来是查重。订单数据的唯一键当然是order_id我用duplicated()查了一下发现有十四行是重复的。我的处理逻辑是保留第一次出现的记录因为同一张订单在数据导出时被重复记录的概率高于同一订单号被二次使用的概率这也是订单数据去重的通用做法。日期字段转类型是个容易踩坑的点。order_date读进来以后是字符串直接groupby也是能跑的但你会发现按月份分组时顺序是乱的按周、按季度统计更是无从下手。我用一行代码把它转成了datetime类型然后顺手提取了month和weekday两个派生字段后面做时间趋势分析非常方便。异常值方面我发现amount字段存在少量负数记录。这里要注意负数不是清洗时用中位数填充就能糊弄过去的因为订单金额为负在实际业务里可能表示退款。退款订单本身是有分析价值的但它在单纯的“销售金额”口径下会拉低整体数值所以我在做销售额分析之前先单独区分了正常订单和退款订单分开统计。这一点也写进了报告的数据说明部分让读者清楚每一个数字的统计口径是什么。import pandas as pd df pd.read_csv(orders.csv) # 删除类目缺失的记录 df df[df[category].notna()].copy() # 城市字段缺失用“未知”填充 df[city] df[city].fillna(未知) # 订单号去重保留第一次出现的记录 df df.drop_duplicates(subsetorder_id, keepfirst) # 日期转换并提取分析字段 df[order_date] pd.to_datetime(df[order_date]) df[month] df[order_date].dt.month df[weekday] df[order_date].dt.weekday print(df.shape) print(df[amount].describe())清洗完成之后数据从十万行变成了九万八千多行整体量级没有大的损失。这里要特别强调一点清洗的每一步都要记录删了多少行、为什么删最好在notebook里写上理由。因为你交的是一份作业老师不仅看你做了什么更看你判断得对不对。3.3 清洗顺序的讲究清洗顺序也是经验活。我的顺序是先处理缺失值再处理重复值最后做类型转换和异常值检查。原因是三个操作之间存在天然的依赖关系重复值不处理后面按订单号聚合时会将同样的订单算两次类型不转换日期维度的分析无法进行异常值不标记金额统计就会被少数极端值污染。还有一个细节我会在清洗前保留一份原始数据的副本用df_raw df.copy()这种方式存下来。万一后面处理过程中出现了问题或者分析时发现某个清洗操作做错了可以直接从原始数据重新开始不需要回滚一大堆代码。这个习惯在真实项目中同样适用我现在做任何数据处理都会保留原始数据层的快照。4. 可视化与作业报告的输出4.1 每张图表都要对应一个结论画图的思路我是这样定的先想清楚每个维度要回答什么问题再决定用什么图表。时间维度回答的是“销售走势怎么样”所以我用了折线图看月度趋势地区维度回答的是“哪些城市贡献了大部分销售额”所以我截取了销售额TOP10的城市画水平条形图商品类目维度回答的是“不同类目的销量和金额结构”所以我画了柱状图和饼图。图表选型有一个经验可以参考趋势数据用折线图对比数据用柱状图占比数据用饼图或环形图数据分布用直方图和箱线图。千万不要反过来用。我第一次作业就犯过把时间序列画成柱状图的错误销售额TOP10用折线图画出来乱七八糟信息根本没法读。图表不是装饰品它是用来辅助理解数据的选型准确比画得好看重要得多。4.2 图表细节与排版规范图表细节是这次作业分数提升的大功臣。我给自己定了一条律每张图必须有标题、坐标轴标签、数据来源或口径说明。图表标题要像论文标题一样能概括整张图的核心信息比如“2024年H1月度销售额走势6月达到峰值”。坐标轴标签要写清楚单位金额类的图表我会在y轴标注“单位元”或者把数值换算成“万元”。中文字体这块踩过坑的同学应该都有印象。Matplotlib默认字体不支持中文画出来的图全是方格。我在notebook第一行加了两行配置解决这个问题import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False第一行指定了中文字体第二行解决负号显示成方块的问题。如果你用的是Mac把SimHei换成Arial Unicode MS或Heiti TC也能达到同样效果。这个配置每次新建notebook都要写一遍属于日常操作里最不起眼但最影响观感的一环。4.3 报告的组织方式报告采用了“结论先行”的结构。开头先用一小段总述说明本次分析的数据范围、清洗概况和三个最核心的发现。接下来每一个维度的小节都按“一句话结论 图表 数据佐证 可能原因”的方式展开。举一个具体例子。在时间维度分析里我发现四月销售额出现了一个明显的低谷而我前三次课程作业的原始版本里只写了一句话“四月销售额最低。”这个结论是对的但没头没尾没有任何分析价值。修改后我补了一段四月销售额为87万元较三月下降约18%结合数据中支付方式的结构变化和该月份的订单量下滑推测可能受到季节性需求回落影响。这样的写法图表佐证和数据细节都在结论一下子就扎实了。报告的最后我加了一页“数据处理说明”简要记录清洗步骤和统计口径。这一步做出来报告的完整度直接提升了一个台阶。老师打开文件的时候不需要主动问我这个数字是怎么来的因为文档自己会说话。5. 常见问题与排查技巧实录5.1 中文字体显示成方框这个问题太典型了单独拿出来说。第一次遇到的时候我以为是自己代码写错了检查了很久才发现是Matplotlib的字体问题。配置两行代码就能解决但如果不配置后面所有图表的标题、标签都会变成方块或问号观感很差。我在这个环节还踩过一个附加坑只配置了正文字体没配置axes.unicode_minus结果到了画图的时候坐标轴的负号又变成了方块。所以两个配置要一起写别漏。5.2 日期分组后顺序错乱这个问题在第一次作业里就出现过这次差点又踩一次。字符串格式的order_date直接参与groupby结果出来的月份顺序是1月、10月、11月、12月、2月……字典序排的完全没法看。解决办法就是先把字段转成datetime类型。如果你用的是其他工具原理也一样分组之前先确认分组字段的类型是你预期中的类型。5.3 饼图比例太小看不清品类维度分析里我一开始画了完整饼图十几个类目的比例挤在一起小类目的标签全部重叠看不清楚。后来我把占比低于百分之一的小类目合并成了“其他”饼图瞬间清爽了很多。这个处理在业务报告里叫“长尾合并”适用于品类过多、重点不突出的场景。如果你的作业也有类似的场景不妨用这个方法处理一下。5.4 提交前自查清单每次提交前我都会对着下面这张表过一遍确认没有低级错误。确认项说明代码能否从头到尾运行一遍特别是别人拿到文件后能不能直接跑通文件路径是否使用相对路径绝对路径换电脑必崩图表是否有标题和坐标轴标签无标签的图表信息不完整报告中每个结论是否有数字支撑不能只有定性描述没有定量证据是否有数据处理说明让读者知道统计口径和清洗逻辑是否保留了中间文件或数据快照事后调整分析时能找回原始状态这个清单我打印出来贴在显示器边上每次作业、每个小项目都过一遍。它帮我挡住了很多次“提交了才发现忘了保存最终版本”的尴尬。5.5 额外想强调的两个坑第一个是关于read_csv的编码问题。作业的数据文件是UTF-8编码直接用pd.read_csv没问题。但如果你是Windows环境有些数据集是GBK编码默认读取会报乱码或解码错误这时需要加encodinggbk参数。具体用哪个编码要看数据本身的格式不确定的时候可以先打开文件看一眼。第二个是notebook的保存习惯。我会在完成代码部分后把notebook导出成HTML文件再整体提交。这样老师不需要打开Jupyter就能看到全部图表和代码视觉效果比直接丢一个.ipynb文件要友好很多。导出后我也会打开HTML快速下拉一遍确认没有渲染问题这一步用不了两分钟但对最终交付的体验提升非常大。6. 第二次作业之后我开始坚持的事6.1 建立自己的作业模板第二次作业结束以后我把整个流程沉淀成了一个模板存成了自己的notebook骨架。模板里面预设好了代码结构、标题层级、Markdown常用写法、中文字体配置甚至连“数据处理说明”那一段的位置都留好了。每次接到新作业我先复制模板再往里面填具体内容省去了大量重复的组织工作。这个习惯帮我省下的时间比想象中多得多。因为作业写多了你会发现大部分数据分析作业的结构是高度相似的先描述数据再清洗数据然后分组统计最后画图写结论。一旦把骨架固定下来剩下的精力就可以集中放在具体数据和分析逻辑上效率翻倍。6.2 复盘时问自己三个问题每次作业提交后我会等结果出来再做一次复盘复盘时只问三个问题。我有没有重复踩上一次作业踩过的坑这次写的代码里有哪些部分可以抽出复用如果数据量变成现在的一百倍我的代码还跑得动吗第三个问题很关键。它能逼着你在写分组统计时认真想一想自己的代码到底是一次性脚本还是可扩展的数据处理流程。作业数据是十万行学会处理十万行和学会处理一千万行的思路是不同的。虽然课程作业不需要考虑那么大的数据量但养成这个习惯对以后面对真实数据时非常有帮助。6.3 给后来者的三个小建议第一个建议不要最后一天开始写宁可提前两天开始、留出修改余地也不要赶在DDL前熬夜输出。第二个建议把代码当成一个故事来写每一个步骤的为什么写清楚你的notebook就是一个完整的故事评分自然会上去。第三个建议多读优秀的公开notebook学习别人是怎么组织分析思路的模仿是提升最快的路径之一。第二次作业让我真正明白了一个道理学生作业和项目作品之间的距离没有想象中那么大。你把每一次练习当作正经项目对待收获就会远远超过那一个分数。